Disegnare un Tooltip con CSS: Può un Bordo Dare Forma ad un Triangolo?

Disegnare un Tooltip con CSS: Può un Bordo Dare Forma ad un Triangolo?

CSS3 aiuta davvero molto nel semplificare il disegno di tooltip: se non fosse per il layout flexbox saremmo ancora obbligati a dover ricorrere ad espedienti come un margine negativo, per centrare un gruppo di elementi. Ma cosa dire riguardo quel piccolo triangolo che caratterizza un tooltip? A volte le vecchie soluzioni non perdono contemporaneità.

Un Triangolo da un Bordo

D'accordo, con CSS un bordo può dare forma ad un triangolo. Ma Come?

Il bordo di un elemento HTML non è reso dal browser come un unico elemento grafico, in effetti un bordo è costituito da quattro sezioni distinte, ognuna delle quali può avere caratteristiche specifiche. Inoltre negli angoli, dove si incontrano sezioni adiacenti, il rendering è tutto tranne che continuo.

Se provi a disegnare un bordo sufficientemente spesso, e dai ad ogni sezione un colore diverso, vedrai con i tuoi occhi di cosa sto parlando: quattro trapezi isosceli che compongono il bordo.

I quattro trapezi isosceli che compongono il bordo
Il bordo di un elemento HTML è composto da quattro trapezi isosceli.

Puoi ottenere il risultato sopra con uno snippet come questo:

1.sample-element {
2  border-top-color: coral;
3  border-right-color: cadetblue;
4  border-bottom-color: darkorchid;
5  border-left-color: lightblue;
6  border-style: solid;
7  border-width: 20px;
8}

Hai scovato il triangolo? Ancora no? Allora prova a far collassare su se stesso l'elemento HTML rimuovendo contenuto e padding, o in alternativa, impostando a zero width, height e padding.

Risultato: quattro triangoli a nostra disposizione.

Quattro triangoli a partire da un bordo multicolore.
Quattro triangoli a partire da un bordo multicolore.

La buona notizia è che questa tecnica è applicabile anche agli pseudo-elementi!

Il Punto di Inizio

Dopo questa breve premessa, possiamo iniziare a programmare!

Siccome è buona abitudine non strafare con il markup, andremo a disegnare il tutto con tre <span>. Perché non usare dei <div>? Perché l'elemento span ci permetterà di inserire il nostro tooltip sia in elementi HTML inline che block senza il rischio di invalidare il markup.

1<span class="tooltip-wrapper">
2  <span class="tooltip">I am a Tooltip!</span>
3  <span class="help-point">?</span>
4</span>

Per iniziare, scriviamo le nostre prime linee di CSS per dar forma ad un disco, con un punto interrogativo nel mezzo, a partire all'elemento .help-point:

1.tooltip-wrapper .help-point {
2  background-color: #333;
3  border-radius: 50%;
4  color: #fff;
5  cursor: default;
6  display: flex;
7  font-size: 0.65rem;
8  font-weight: bold;
9  height: 1rem;
10  width: 1rem;
11
12  /* Centra verticalmente il punto interrogativo */
13  align-items: center;
14
15  /* Centra orizzontalmente il punto interrogativo */
16  justify-content: center;
17}

Il codice appena scritto si traduce in questo:

Elemento HTML a cui è dato l'aspetto di un disco
Uno `span` contenente un punto interrogativo a cui è dato l'aspetto di un "help point".

Dare Forma al Tooltip

Il tooltip in se è composto da due parti:

  • un rettangolo posizionato in modo assoluto, avente un'ampiezza fissa e modellato a partire dall'elemento .tooltip
  • un triangolo posizionato in modo assoluto, nato dallo pseudo-elemento .tooltip::before grazie alla tecnica descritta all'inizio dell'articolo
La struttura del tooltip.
La struttura del tooltip.

Siccome .tooltip è posizionato in modo assoluto, l'elemento contenitore (.tooltip-wrapper) collasserà alla dimensione dell'elemento .help-point. In questo modo, nel momento in cui applichiamo delle "regole flexbox" per centrare il tooltip relativamente a .tooltip-wrapper, otterremo che il tooltip sarà automaticamente centrato anche rispetto all'elemento .help-point.

Ecco il codice:

1.tooltip-wrapper {
2  position: relative;
3  
4  /**
5   * Centra il tooltip orizzontalmente 
6   * rispetto a .tooltip-wrapper.
7   */
8  display: inline-flex;
9  justify-content: center;
10  }
11  .tooltip-wrapper:hover .tooltip {
12    display: flex;
13  }
14  .tooltip-wrapper .tooltip {
15    background-color: #333;
16    border-radius: 4px;
17    box-shadow: 0px 2px 4px #07172258;
18    color: #fff;
19    display: none;
20    font-size: 0.68rem;
21    line-height: 1.35em;
22    padding: 0.5em 0.7em;
23    position: absolute;
24    text-align: center;
25    width: 7rem;
26    z-index: 1;
27
28    /**
29     * 100% dell'altezza di .tooltip-wrapper
30     *
31     * 0.6em è l'altezza del triangolo ( .tooltip::before )
32     *
33     * 2px è uno spazio vuoto arbitrario tra
34     * la punta del triangolo e .help-point
35     */
36    bottom: calc( 100% + 0.6em + 2px );
37
38    /**
39     * Centra il triangolo orizzontalmente 
40     * rispetto l'elemento .tooltip
41     */
42    justify-content: center;
43  }
44  .tooltip-wrapper .tooltip::before {
45    content: "";
46    display: block;
47    border-style: solid;
48    position: absolute;
49
50    /**
51     * Impostare a 0 l'ampiezza del bordo
52     * inferiore assicura che il tooltip scompaia
53     * anche quando il cursore viene spostato verso
54     * l'alto, fuori dall'elemento .tooltip-wrapper
55     */
56    border-width: 0.6em 0.8em 0;
57
58    /* Mostriamo solo il triangolo superiore */
59    border-color: transparent;
60    border-top-color: #333;
61
62    /* 100% dell'altezza di .tooltip */
63    top: 100%;
64  }

L'intera Cascata

Ovviamente ci sono varianti al disegno di un tooltip proposto in questo articolo, ma i concetti base continuano ad essere validi.

Per riepilogare, il markup da cui siamo partiti è questo:

1<span class="tooltip-wrapper">
2  <span class="tooltip">I am a Tooltip!</span>
3  <span class="help-point">?</span>
4</span>

E la cascata, riassettata, di regole CSS usate per dare al tooltip l'aspetto voluto è quella che segue. Non dimenticare di armeggiare con questo codice, di rifattorizzarlo, e di usarlo come punto di partenza per qualcosa di creativo!

1.tooltip-wrapper {
2  display: inline-flex;
3  justify-content: center;
4  position: relative;
5  }
6  .tooltip-wrapper:hover .tooltip {
7    display: flex;
8  }
9  .tooltip-wrapper .tooltip {
10    background-color: #333;
11    border-radius: 4px;
12    bottom: calc( 100% + 0.6em + 2px );
13    box-shadow: 0px 2px 4px #07172258;
14    color: #fff;
15    display: none;
16    font-size: 0.68rem;
17    justify-content: center;
18    line-height: 1.35em;
19    padding: 0.5em 0.7em;
20    position: absolute;
21    text-align: center;
22    width: 7rem;
23    z-index: 1;
24  }
25  .tooltip-wrapper .tooltip::before {
26    border-width: 0.6em 0.8em 0;
27    border-color: transparent;
28    border-top-color: #333;
29    content: "";
30    display: block;
31    border-style: solid;
32    position: absolute;
33    top: 100%;
34  }
35  .tooltip-wrapper .help-point {
36    align-items: center;
37    background-color: #333;
38    border-radius: 50%;
39    color: #fff;
40    cursor: default;
41    display: flex;
42    font-size: 0.65rem;
43    font-weight: bold;
44    height: 1rem;
45    justify-content: center;
46    width: 1rem;
47  }
Il tooltip finito.
Il tooltip finito.
TOP