Bubble Point Tooltips mit CSS3 & jQuery

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ich brauchte einige Tooltips für ein Ding. Als ich nach etwas Inspiration suchte, musste ich nicht weiter als zu meinem Dock gehen

Die Inspiration: Kontextmenüs vom OS X Dock

Hier bin ich gelandet

Demo ansehen

Das HTML: Sauber halten

Links können ohne jegliche Schnörkel-Codierung Tooltips in HTML haben. Geben Sie einem Link einfach ein title-Attribut.

<a href="#" title="Hi, I'm a tooltip thingy.">link</a>

Wenn Sie dann ein bis zwei Sekunden mit der Maus über diesen Link fahren, erhalten Sie die gelbe Box.

Standard-Tooltip in so ziemlich jedem Browser.

Wir werden das nicht verändern. Unser HTML wird genau so aussehen, wie oben gezeigt.

Die Sache ist, dass diese gelbe Box absolut ungestaltbar ist. Vielleicht wird das eines Tages möglich sein, wenn Shadow-DOM-Sachen wie diese spezifiziert sind, aber heute ist es in keinem Browser möglich. Also werden wir etwas JavaScript ausführen, das dieses Attribut extrahiert und <div>-Elemente mit demselben Text erstellt, die wir nach Bedarf positionieren/verstecken/anzeigen werden.

Das JavaScript: jQuery Plugin

Wie üblich an dieser Stelle verwenden wir jQuery. Dies ist die perfekte Art von Funktionalität, um sie in ein Plugin zu verwandeln. Möglicherweise möchten Sie diese Funktionalität auf eine beliebige Sammlung von Elementen Ihrer Wahl anwenden und sie auch verketten, sodass das Plugin-Muster ideal ist.

Der Aufruf wird so einfach sein wie

$("article a[title]").tooltips();

Dadurch werden alle Links mit Titeln, die sich in <article>-Elementen befinden, mit Tooltips versehen. Sie könnten diesen Selektor beliebig wählen.

Unser Plugin wird Folgendes tun

  1. Durchlaufen Sie jeden Link
  2. Erstellen Sie ein (verstecktes) div.tooltip für jeden von ihnen, dessen Text dem Titelattribut des Links entspricht.
  3. Entfernen Sie das Titelattribut des Links (die einzige Möglichkeit, das standardmäßige gelbe Popup-Fenster loszuwerden)
  4. Wenn der Link mit der Maus überfahren wird...
  5. Positionieren Sie den Tooltip entsprechend und blenden Sie ihn ein.
  6. Wenn der Link nicht mehr mit der Maus überfahren wird...
  7. Blenden Sie den Link aus.

Massiver Code-Dump, kommentiert zu Ihrem Vergnügen

// IIFE to ensure safe use of $
(function( $ ) {

  // Create plugin
  $.fn.tooltips = function(el) {

    var $tooltip,
      $body = $('body'),
      $el;

    // Ensure chaining works
    return this.each(function(i, el) {

      $el = $(el).attr("data-tooltip", i);

      // Make DIV and append to page 
      var $tooltip = $('<div class="tooltip" data-tooltip="' + i + '">' + $el.attr('title') + '<div class="arrow"></div></div>').appendTo("body");

      // Position right away, so first appearance is smooth
      var linkPosition = $el.position();

      $tooltip.css({
        top: linkPosition.top - $tooltip.outerHeight() - 13,
        left: linkPosition.left - ($tooltip.width()/2)
      });

      $el
      // Get rid of yellow box popup
      .removeAttr("title")

      // Mouseenter
      .hover(function() {

        $el = $(this);

        $tooltip = $('div[data-tooltip=' + $el.data('tooltip') + ']');

        // Reposition tooltip, in case of page movement e.g. screen resize                        
        var linkPosition = $el.position();

        $tooltip.css({
          top: linkPosition.top - $tooltip.outerHeight() - 13,
          left: linkPosition.left - ($tooltip.width()/2)
        });

        // Adding class handles animation through CSS
        $tooltip.addClass("active");

        // Mouseleave
      }, function() {

        $el = $(this);

        // Temporary class for same-direction fadeout
        $tooltip = $('div[data-tooltip=' + $el.data('tooltip') + ']').addClass("out");

        // Remove all classes
        setTimeout(function() {
          $tooltip.removeClass("active").removeClass("out");
          }, 300);

        });

      });

    }

})(jQuery);

Ein paar Dinge zu beachten: **1)** Die endgültige Demo wird die Tooltips ein wenig animiert haben. Nichts davon geschieht hier im JavaScript. Animationen sind Design. Design ist CSS. Daher machen wir das alles in CSS. **2)** Eine kleine Design-Besonderheit bei diesen ist, dass die Tooltips in die gleiche Richtung ein- und ausgleiten. In CSS ist dies durch Hinzufügen und Entfernen einer einzigen Klasse und die Verwendung von Übergängen nicht wirklich möglich. Der Übergang läuft beim Entfernen der Klasse rückwärts und gleitet somit in die gleiche Richtung, aus der er kam. Durch die Verwendung eines setTimeout können wir eine temporäre Klasse anwenden und diese ebenfalls animieren. Wenn Sie elegantere Ideen dazu haben, lassen Sie es mich in den Kommentaren unten wissen.

Eine semantische Enttäuschung?

Das Hinzufügen von Divs am Ende des Dokuments fühlt sich wie eine Enttäuschung an; es fühlt sich einfach nicht sehr semantisch an. Sie sind in keiner sinnvollen Weise durch reines HTML mit den Links verbunden, von denen sie stammen.

Auch das Entfernen des Titel-Tags ist für mich nicht ganz richtig. Ich habe gehört, dass sie für die Zugänglichkeit sowieso nicht viel bringen, aber trotzdem. Ich wünschte, preventDefault() würde das Verhindern des Anzeigens bewirken, aber das tut es nicht.

Wenn Sie Ideen dazu haben, lassen Sie es uns in den Kommentaren unten wissen.

Das CSS: Es zählt auf Kleinigkeiten an

Beachten Sie im OS X-Screenshot oben in diesem Artikel, dass der Hintergrund und die Ränder selbst leicht transparent sind. Das konnte ich hier nicht erreichen. Diese Dinge sind im Allgemeinen möglich, aber der spitze Pfeil nach unten ist ein zusätzliches Element und wie die Ränder und Hintergründe miteinander verbunden sind, geschieht nur durch Überlappung, und es sieht mit jeglicher Transparenz schlecht aus. Also, solide Farben, kein Problem.

Oftmals sind spitze Pfeile wie hier mit keinem zusätzlichen Markup oder Bildern machbar, indem Pseudo-Elemente und CSS-Dreiecke verwendet werden. In unserem Fall verwenden wir ein Pseudo-Element, aber wir benötigen auch ein echtes Element. Das echte Element (der <span>, den das JavaScript in jedem Tooltip <div> eingefügt hat) dient als Positionsbox und erledigt das Zuschneiden. Das Pseudo-Element ist der eigentliche Zeiger. Eine Box, die genauso gestaltet ist wie der Tooltip, nur um 45 Grad gedreht und von ihrem Elternteil abgeschnitten. Hier sind die Schaltpläne

Das Ding kommt in das Ding

Und so

.tooltip, .arrow:after {
  background: black;
  border: 2px solid white;
}

.tooltip {
  pointer-events: none;
  opacity: 0;
  display: inline-block;
  position: absolute;
  padding: 10px 20px;
  color: white;
  border-radius: 20px;
  margin-top: 20px;
  text-align: center;
  font: bold 14px "Helvetica Neue", Sans-Serif;
  font-stretch: condensed;
  text-decoration: none;
  text-transform: uppercase;
  box-shadow: 0 0 7px black;
}
.arrow {
  width: 70px;
  height: 16px;
  overflow: hidden;
  position: absolute;
  left: 50%;
  margin-left: -35px;
  bottom: -16px;
}
.arrow:after {
  content: "";
  position: absolute;
  left: 20px;
  top: -20px;
  width: 25px;
  height: 25px;
  box-shadow: 6px 5px 9px -9px black,
              5px 6px 9px -9px black;
  transform:      rotate(45deg);
}
.tooltip.active {
  opacity: 1;
  margin-top: 5px;
  transition: all 0.2s ease;
}
.tooltip.out {
  opacity: 0;
  margin-top: -20px;
}

Beachten Sie, dass die Klasse .active für die Einblendanimation zuständig ist und die Klasse .out für das Ausblenden.

Danksagung

Dank an Adrian Adkison für einige Ideen und Code unterwegs.

Fairer Hinweis zu Opera

Opera unterstützt pointer-events in CSS nicht, daher wird die gesamte Demo nicht zu funktionieren scheinen. Das liegt daran, dass die Tooltips tatsächlich direkt über den Links positioniert sind, wobei ihre Opazität auf 0 reduziert ist. Wenn Sie es in Opera reparieren möchten, müssen Sie sie im JavaScript buchstäblich auf display none/block setzen oder CSS verwenden, um sie weit genug von den Links zu verschieben, damit sie die Klickbarkeit nicht beeinträchtigen. Wenn jemand diese Änderung vornehmen möchte, aber ansonsten genau wie diese Demo funktionieren soll, bin ich gerne bereit, sie zu aktualisieren.

Demo

Siehe den Stift
Bubble Point Tooltips
von Chris Coyier (@chriscoyier)
auf CodePen.