Disegnare una Freccia Sinistra con gli Pseudo‑elementi CSS

Mentre stavo lavorando sull'area personale aperta di recente, è sorta la necessità di aggiungere una freccia ad un link di ritorno senza che venissero apportate modifiche al markup, principalmente perché non ne avevo il controllo. La soluzione si è presentata in modo del tutto naturale: usare gli pseudo-elementi ::before e ::after per disegnare rispettivamente la punta e l'asta della freccia.

Inutile dirti che il risultato è stato appagante. Quanto segue ne è uno screenshot:

Una freccia di ritorno disegnata con gli pseudo-elementi CSS.
Una freccia di ritorno disegnata con gli pseudo-elementi CSS.

Styling Preliminare

Come anticipato, tutto lo styling gravita attorno ad un singolo tag, un tag <a>, quindi il markup è davvero minimalista:

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

E il CSS di base non è altrimenti:

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

    /**
     * Se impostato su un valore maggiore del 'font-size', 
     * dovrai tenere conto della differenza tra 'line-height' 
     * e 'font-size' per centrare la feccia verticalmente ed
     * allinearla al testo.
     **/
    line-height: 1;

    /* Fa dello spazio per la freccia */
    padding-left: 15px;

    /* La freccia verrà posizionata in modo assoluto */
    position: relative;
}

La Punta

Immagina un quadrato trasparente con un bordo solo lungo due lati adiacenti. Ora immagina di ruotare il quadrato in modo che l'angolo visibile punti ad ovest. Ecco che hai in mente la punta di una freccia orientata verso sinistra:

.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;

    /* Queste due righe centrano verticalmente la punta della freccia */
    margin-top: -3px;
    top: 50%;

    /**
     * La freccia schizza verso sinistra quando 
     * il puntatore viene posizionato sopra il link.
     **/
    transition: left 0.1s;

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

L'asta

L'asta della nostra freccia è un semplice segmento, quindi ci occorre solo disegnare un rettangolo orizzontale, dargli un colore di sfondo, e posizionarlo in armomia con la punta disegnata poc'anzi:

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

    /* Dobbiamo animare anche l'asta, per poter guardare ad una freccia in movimento */
    transition: left 0.1s;
}

Giusto per lasciare poco all'immaginazione:

Gli pseudo-elementi che compongono la freccia.
Le parti grafiche che compongono la freccia.

Hai notato il quadrato azzurro? È una rappresentazione dello pseudo-elemento ::before, l'elemento che con il suo bordo da 2px di spessore veste il ruolo della punta della freccia.

Manca Qualcosa

Il disegno è completo, la freccia è visibile, ma posizionando il puntatore sopra il link non accade nulla. Questo perché gli ingredienti per uno stato :hover non ci sono tutti, ancora. Abbiamo bisogno di una regola finale:

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

L'intera Cascata

.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;
}

Il mio obiettivo nello scrivere questo codice era quello di disegnare una freccia di ritorno senza fronzoli e senza dover ricorrere allo JavaScript, siccome nel mio caso solo con del JavaScript avrei potuto inserire un tag figlio nel tag <a>. Perché un tag figlio? Perché se volessimo aggiungere alla freccia un box-shadow, o più in generale, applicare dello styling più complesso, ne avremmo definitivamente bisogno. In tal caso infatti, la freccia prenderebbe forma dalla combinazione di tre segmenti: due, gli pseudo-elementi del tag figlio, formerebbero la punta, invece il terzo, il tag figlio stesso, fungerebbe da asta.