Tooltips mit CSS

Marcel Wolf, 16. September 2016
Lesezeit: 8 Minuten

Tooltips sind eine simple Möglichkeit die User Experience merklich zu verbessern. Viele CSS-Frameworks unterstützen ihr CSS heutzutage mit JavaScript. So ist es nicht verwunderlich, dass viele CSS-Frameworks auch für Tooltips eine JavaScript-Verwendung vorsehen. Im nachfolgenden Beitrag stellen wir eine Variante für Tooltips in reinem CSS vor.

In größeren Applikationen sammeln sich naturgemäß jedoch einige Tooltips an, die dann durch den entsprechenden JavaScript Teil initialisiert werden müssen. Hinzu kommt, dass Single Page Applications einen eigenen Lifecycle haben, die Tooltips müssen dadurch häufig in jedem Render-Zyklus initialisiert werden. Darüber hinaus kann es schnell passieren, dass die Initialisierung zum richtigen Zeitpunkt vergessen wird oder versehentlich ein Tooltip doppelt initialisiert wird.

Das führt nicht nur zu übermäßig viel Code sondern schlägt sich auch in der Render-Performance nieder.

Doch auch wenn JavaScript viele Vorteile mit sich bringt, warum nicht den Code schlank und weniger fehleranfällig halten und eine Lösung basierend auf dem immer mächtiger werdenden CSS anstreben?

Getting started

Um nicht unnötig viel HTML-Code zu produzieren und so Schreibarbeit zu sparen, soll der Tooltip direkt an das jeweilige Element gebunden werden.  Die Position des Tooltips, sowie den Text, der angezeigt werden soll, steuern wir über data-Attributes. Am Ende wird unser Tooltip so aussehen:

/uploads/tooltip_semantic_8aebb8c915.png

Dazu der HTML-Teil:

Copy
<button type="button" class="my-button-class" data-tooltip="Tooltip Info">
    Top Center 
</button>

Schritt 1 – Der Tooltip

Der komplette Tooltip wird über die Selektoren :after und :before abgebildet. Die einzige Eigenschaft, die das Element, welches den Tooltip beinhaltet, erhält, ist „position: relative“, da der Tooltip an sich mit der Nase und dem Text-Container zwei Elemente enthält, die absolut positioniert sind.

Copy
[data-tooltip] { 
    position: relative; 
}

Schritt 2 – Nase des Tooltips

Die Nase des Tooltips, hier blau eingefärbt, soll verdeutlichen auf welches Element sich das Tooltip bezieht.

/uploads/tooltip_nase_1_79db0537a9.png

Die Nase wird durch den Selector :before hinzugefügt. Sie besteht aus einem leeren Container mit Borders.

/uploads/tooltip_nose_79d63f211e.png

Die Breite des Elements berechnet sich aus der Addition der linken und rechten Border, 8px + 8px = 16px. Die Höhe gleicht der top Border. Die Nase wird absolut zum Top Element positioniert.

Left wird auf 50% gesetzt um die Nase mittig zu positionieren. Da das Element so aber bei 50% erst anfängt, müssen wir es noch ein wenig versetzen. Um das zu erreichen erhält es ein margin-left von -8px.

Vertikal wird die Nase 100% von bottom ausgerichtet. Um die Nase etwas abzusetzen geben wir ihr noch eine margin-bottom von -0.1em.

Da wir später den Tooltip noch animieren möchten und um unschöne Nebeneffekte bezüglich der Visibility und des Klickverhaltens vorzubeugen, setzen wir die Visibility auf hidden und die Pointer-Events auf none.

Copy
[data-tooltip]:before {
    border-left: solid transparent 8px;
    border-right: solid transparent 8px;
    border-top: solid #0064ad 8px;
    content: " ";
    left: 50%;
    margin-left: -8px;
    position: absolute;
    width: 0;
    height: 0;
    bottom: 100%;
    margin-bottom: -.1em;
    pointer-events: none;
    visibility: hidden;
}

Schritt 3 - Tooltip Container

Der Container des Tooltips beinhaltet den Text, der angezeigt werden soll. Wir fügen den Container mit Hilfe des :after-Selectors hinzu. Der Container wird von links mit 0% und von unten mit 100% ausgerichtet. Damit er sich etwas abhebt erhält er ein margin von 0.5em. Auch dieses Element wird absolut positioniert. Wir fügen noch ein paar paddings hinzu, damit der Tooltip besser wirkt und nicht so geschrumpft, bzw. gequetscht aussieht. Um zu gewährleisten, dass der Tooltip Container auch sichtbar wird, sollte der z-Index eingestellt werden. Dieser Wert kann jedoch je nach Umgebung, in die der Tooltip eingebettet werden soll, variieren. Wir geben dem Tooltip Container ein Border-Radius von 2px um die Ecken etwas abzurunden, auch hier kann je nach Geschmack der Wert erhöht oder verringert werden. Des Weiteren fügen wir an den Container noch eine leichte Schattierung hinzu. Der eigentliche Text, der als Tooltip angezeigt werden soll, wird über das content Attribut hinzugefügt. Mit content: attr(data-tooltip) sorgen wir dafür, dass im Content der Text aus dem data-tooltip Attribut steht.

/uploads/tooltip_container_1edf94959a.png

Copy
[data-tooltip]:after {
    top: auto;
    right: auto;
    left: 0%;
    bottom: 100%;
    margin-bottom: .5em;
    pointer-events: none;
    visibility: hidden;
    content: attr(data-tooltip);
    position: absolute;
    text-transform: none;
    text-align: left;
    white-space: nowrap;
    font-size: 14px;
    line-height: 1.4285em;
    max-width: none;
    background: #0064ad;
    padding: 7px;
    font-weight: 400;
    font-style: normal;
    color: white;
    z-index: 1031;
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    -ms-border-radius: 2px;
    -o-border-radius: 2px;
    border-radius: 2px;
    
    //Shadow
    -webkit-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
    -moz-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
    -ms-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
    -o-box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
    box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.28);
}

Schritt 4 - Animationen

Damit der Tooltip nicht einfach aufploppt und um die User Experience anzuheben, können wir das Erscheinen des Tooltips animieren. Wir müssen das sowohl für die Nase des Tooltips (im :before Selector), als auch für den Tooltip Container (im :after Selector) anpassen. Wir erreichen das, in dem wir jeweils im :after und :before Selector eine Transition ablegen, die die transform Anweisung ausführen soll. Die Länge der Animation setzen wir auf 0.25 Sekunden und reichern diese mit einem ease-out Effekt an.

Copy

[data-tooltip]:before {
    opacity: 1;
    -webkit-transition: transform .25s ease-out;
    -moz-transition: transform .25s ease-out;
    -ms-transition: transform .25s ease-out;
    -o-transition: transform .25s ease-out;
    transition: transform .25s ease-out;
}

[data-tooltip]:after {
    opacity: 1;
    -webkit-transition: transform .25s ease-out;
    -moz-transition: transform .25s ease-out;
    -ms-transition: transform .25s ease-out;
    -o-transition: transform .25s ease-out;
    transition: transform .25s ease-out;
}

Der oben angefügte Code beinhaltet also die Animation. Es fehlt nun noch eine Definition des Animationszeitpunktes und was beim Transform passieren soll.

Schritt 5 - Hover

Am Häufigsten macht es Sinn den Tooltip einzublenden, wenn der User mit der Maus über ein Element hovert. Zuerst setzen wir im Hover die Visibility auf sichtbar und holen die Pointer-Events, die wir ursprünglich auf none gesetzt hatten, zurück.

Copy
[data-tooltip]:hover:before, 
[data-tooltip]:hover:after { 
    visibility: visible; 
    pointer-events: auto; 
}

Als nächstes müssen wir noch festlegen, was genau beim Transformieren des Elements und somit auch bei der Animation passieren soll. Wir möchten in diesem Fall erreichen, dass der Tooltip aus dem Element, über welches gehovert wird, raus fährt. Dafür verschieben wir die Elemente im :before und :after Selektor um die Y-Achse.

Copy

[data-tooltip]:hover:before {
    -webkit-transform: translateY(-10px);
    -moz-transform: translateY(-10px);
    -ms-transform: translateY(-10px);
    -o-transform: translateY(-10px);
    transform: translateY(-10px);
}

[data-tooltip]:hover:after {
    -webkit-transform: translateY(-10px);
    -moz-transform: translateY(-10px);
    -ms-transform: translateY(-10px);
    -o-transform: translateY(-10px);
    transform: translateY(-10px);
}

Ausblick - Sass

Wir haben nun einen fertigen Tooltip, der jedoch nur für eine Richtung funktioniert und zudem nur in einer Farbe – alles geschrieben in Vanilla CSS. Möchte man nun ein breiteres Spektrum an Tooltips in seiner Applikation anbieten, etwa in verschiedenen Farben oder den Tooltip lieber links des Elements anzeigen anstatt über dem Element, könnte man natürlich den Code für die verschiedenen Varianten einfach kopieren und anpassen. Das vergrößert den Anteil an CSS Code aber unnötig. Daher bietet es sich an den Code für den Tooltip in ein Sass Mixin auszulagern und Parameter wie Farbe, Richtung, etc zu übergeben.