Drawing a Go-back Arrow with CSS Pseudo‑elements

While working on the personal area opened recently, the need arose to add a left arrow to a go‑back link without making any changes to the markup, mainly because I had no control over it. The solution followed naturally: use the ::before and ::after pseudo-elements to draw respectively the point and the shaft of the arrow.

Needless to tell you that the end result was rewarding. The following is a screenshot:

A go-back arrow drawn with CSS pseudo-elements.
A go-back arrow drawn with CSS pseudo-elements.

Preliminary Styling

As anticipated, all the styling gravitates around a single tag, an <a> tag, so the markup is very minimalistic:

<a class="go-back">Go Back</a>

And the base CSS is not otherwise:

.go-back {
    color: #c16b00;
    font-size: 16px;
    font-weight: 600;
    font-family: 'Open Sans', sans-serif;

    /**
     * If you set it to a value higher than the 'font-size', 
     * you will have to take account of the difference 
     * between the 'line-height' and the 'font-size' 
     * to vertically centre the arrow and align it with the text.
     **/
    line-height: 1;

    /* Makes some place for the arrow */
    padding-left: 15px;

    /* The arrow will be absolutely positioned */
    position: relative;
}

The Point

Imagine a transparent square with a border only on two adjacent sides. Now imagine to rotate the square so that the visible corner points west. You have the point of a left arrow in mind:

.go-back::before {
    border-color: #c16b00;
    border-style: solid;
    border-width: 0 0 2px 2px;
    content: "";
    display: block;
    height: 6px;
    left: 0px;
    position: absolute;
    width: 6px;

    /* These two lines vertically centre the point of the arrow */
    margin-top: -3px;
    top: 50%;

    /* The arrow sprints to the left when the link is hovered */
    transition: left 0.1s;

    transform: rotate( 45deg );
    -webkit-transform: rotate( 45deg );
}

The Shaft

The shaft of our arrow is a plain segment, so we just need to draw a horizontal rectangle, give it a background colour, and place it in harmony with the point drawn before:

.go-back::after {
    background: #c16b00;
    content: "";
    display: block;
    height: 2px;
    left: 0px;
    position: absolute;
    top: 50%;
    width: 11px;

    /* We need to animate the shaft too, to be able to look at a moving arrow */
    transition: left 0.1s;
}

Just to leave very little to the imagination:

The pseudo-elements composing the arrow.
The graphical parts composing the arrow.

Have you noticed the square in light blue? It is a representation of the ::before pseudo-element, the element whose 2px-wide border plays the role of the point of the arrow.

Something is Missing

The drawing is complete, the arrow is visible, but when hovering the link nothing changes. That's because the ingredients for an :hover state are not all there, yet. We need a final rule:

.go-back:hover::before,
.go-back:hover::after {
    left: -3px;
}

The Whole Cascade

.go-back {
    color: #c16b00;
    font-family: 'Open Sans', sans-serif;
    font-size: 16px;
    font-weight: 600;
    line-height: 1;
    padding-left: 15px;
    position: relative;
}
.go-back::before,
.go-back::after {
    content: "";
    display: block;
    left: 0px;
    position: absolute;
    top: 50%;
    transition: left 0.1s;
}
.go-back::before {
    border-color: #c16b00;
    border-style: solid;
    border-width: 0 0 2px 2px;
    height: 6px;
    margin-top: -3px;
    width: 6px;

    transform: rotate( 45deg );
    -webkit-transform: rotate( 45deg );
}
.go-back::after {
    background: #c16b00;
    height: 2px;
    width: 11px;
}
.go-back:hover::before,
.go-back:hover::after {
    left: -3px;
}

My goal on writing this code was drawing a plain go-back arrow without having to resort to JavaScript, since in my case only with JavaScript I could have inserted a child tag into the <a> tag. Why a child tag? Because if you want to add a box-shadow to the arrow, or more generally, do any more complex styling, you would definitely need one. In such a case in fact, the arrow would take shape from the combination of three segments: two, the pseudo-elements of the child tag, would form the point, instead the third, the child tag itself, would act as a shaft.