Einfach herausragend! Die neue Popover API und CSS Anchor Positioning

Menüs, Tooltips, Datumsauswahlen oder Dialoge – das Web steckt voller Popover-Inhalte. Trotz ihrer weiten Verbreitung existieren kaum native HTML-Elemente für diese Komponenten (außer für Dialoge). Und ihre Implementierung erfordert eine ganze Menge JavaScript.

Doch die neue Popover API in Kombination mit CSS Anchor Positioning ändert alles. Die Darstellung von einzelnen Elementen über anderen Seiteninhalten wird damit für Entwickler:innen zum Kinderspiel.

Ein Skateboarder beim Sprung in der Luft. Foto: © Zachary DeBottis / pexels.com

Ich habe zwei Demos mit Beispielen für Popover-Inhalte vorbereitet. Wir werden sowohl die technischen Aspekte als auch die Barrierefreiheit der neuen Funktionen eingehend betrachten.

Was können wir damit machen?

Ich mag das Motto: Zeigen, nicht erzählen! Deshalb habe ich zwei Demos erstellt, um die Möglichkeiten der neuen API zu veranschaulichen.

Im Moment funktionieren die Beispiele nur in Chrome Canary, dem Nightly Build für Entwickler:innen. Öffnet den Browser, ruft die Seite chrome://flags auf und aktiviert dort die experimentellen Web-Plattform-Funktionen.

Warnung: Die Anker-Positionierung ist noch sehr experimentell. Daher können die Demos eventuell nicht funktionieren, falls sich die Spezifikation ändert.

Beispiel 1: Benutzerdefinierter Tooltip

Standard-Tooltips, die mit dem Attribut title erstellt werden, sind ziemlich langweilig. Deshalb habe ich mich an einem schicken benutzerdefinierten Tooltip versucht. Klickt auf die Info-Schaltfläche neben der Überschrift:

Ich habe mein Bestes gegeben, um den Tooltip barrierefrei zu gestalten. Dazu bin ich den Vorgaben des Tooltip Pattern im ARIA Authoring Practices Guide gefolgt. Leider gibt es noch keinen Konsens zur idealen Implementierung. Darüber hinaus bietet die Popover API noch keinen Mechanismus für Hover- und Fokus-Events.

Beispiel 2: Menü mit einer Reihe von Aktionen

Ich habe auch eine Demo für ein barrierefreies Menü erstellt. Jeder Eintrag in der Liste der ausgeliehenen Bücher enthält eine Schaltfläche, die ein Menüfeld mit einer Reihe von Aktionen für jedes Buch einblendet:

Meine Implementierung folgt dem Menu and Menubar Pattern, das im ARIA Authoring Practices Guide definiert ist. Ich habe die entsprechenden ARIA-Rollen und -Eigenschaften verwendet und auch (die meisten) der empfohlenen Tastatur-Interaktionen implementiert.

Schauen wir uns nun die verschiedenen Bausteine an, die ich zur Erstellung dieser Komponenten verwendet habe.

Das magische popover-Attribut

Dieses HTML-Attribut verwandelt jedes Element in einen Popover-Inhalt. Die HTML-Spezifikation besagt:

All HTML elements may have the popover content attribute set. When specified, the element won't be rendered until it becomes shown, at which point it will be rendered on top of other page content.

Dieser Popover-Inhalt ist immer nicht-modal, d. h. Nutzer:innen können weiterhin mit dem Rest der Seite interagieren, während das Popover geöffnet ist. Wenn ihr ein modales Popover (z. B. einen Bestätigungs-Dialog) anzeigen wollt, solltet ihr das Element <dialog> verwenden.

Wie ihr ein Popover erstellt

Um ein Popover zu erstellen, fügt ihr das Attribut popover zu einem Element hinzu und definiert eine id. Anschließend setzt ihr das Attribut popovertarget mit dem Wert der ID des Popovers auf jenes Element, welches das Popover öffnet. Ein Beispiel:

<button popovertarget="popover-1"> Info </button> <div id="popover-1" popover> Hi, I'm a popover! </div>

Das war's! Ihr habt gerade ein Popover mit ein paar Zeilen HTML und null JavaScript erstellt. Genial!

Eingebaute Features der Popover API

Wenn ihr das popover-Attribut verwendet, erhaltet ihr die folgenden Funktionen mit dazu:

  • Platzierung im Top-Layer: Popover-Inhalte werden automatisch im Top-Layer angezeigt, einer separaten Ebene, die über allen anderen Inhalten im Webdokument liegt. Ihr müsst euch nicht länger um die DOM-Reihenfolge oder den z-Index Sorgen machen.
  • Light-dismiss: Wenn ihr außerhalb des Popover-Bereichs klickt, wird das Popover geschlossen und der Fokus wieder auf das auslösende Element zurückgesetzt.
  • Barrierefreie Tastaturbedienung: Wenn das Popover geöffnet ist, könnt ihr die ESC-Taste drücken, um das Popover zu schließen und den Fokus wieder auf das auslösende Element zu setzen.
  • Semantische Beziehung: Die Verknüpfung eines Popover-Elements mit einer Schaltfläche erzeugt automatisch eine semantische Beziehung für assistive Technologien. Quasi ein eingebautes aria-controls plus aria-expanded.

Weitere Optionen und Styling

Wenn ihr ein Popover mit popovertarget erstellt, blendet die Schaltfläche das Popover standardmäßig ein und aus. Alternativ könnt ihr auch einen expliziten Wert für das Attribut popovertargetaction festlegen:

  • "hide": Die Schaltfläche blendet ein angezeigtes Popover aus. Das kann nützlich sein, wenn ihr innerhalb eines Popovers eine Schaltfläche zum Schließen anbieten möchtet.
  • "show": Die Schaltfläche blendet ein Popover ein.
  • "toggle": Die Schaltfläche blendet ein Popover ein und aus. Dies ist das Standardverhalten.

Darüber hinaus ist das popover-Attribut eigentlich eine Abkürzung für popover="auto". Dieser Standardtyp von Popover erzwingt das Schließen anderer Auto-Popovers. Es kann über Light-Dismiss oder eine Schließen-Schaltfläche ausgeblendet werden.

Mit popover="manual" könnt ihr ein manuelles Popover erstellen. Diese Popover werden nicht über Light-Dismiss geschlossen und sie erzwingen auch nicht das Schließen anderer Popover. Ihr müsst sie durch eine explizite Schließ-Aktion ausblenden. Ein möglicher Anwendungsfall für manuelle Popovers sind Alarm-Snackbars, die vom Nutzer bestätigt werden müssen.

Popovers bieten auch nützliche CSS-Funktionen: Mit dem Pseudoelement ::backdrop könnt ihr Effekte auf den Seiteninhalt hinter dem Popover anwenden. Ihr könnt die Pseudoklasse :popover-open verwenden, um das Styling von eingeblendeten Popover-Elementen zu definieren.

CSS Anchor Positioning

Wenn ihr's bis hierher geschafft habt, fragt ihr euch vielleicht: Was ist mit der Position des Popovers auf der Seite? Um den eingeblendeten Inhalt relativ zu einem anderen Element zu positionieren, benötigen wir eine weitere neue, experimentelle Funktion: Anker-Positionierung.

Dieses Feature ist im CSS-Modul CSS Anchor Positioning definiert. Im Moment ist das Dokument noch ein „Working Draft“, aber Chrome bietet die Funktion bereits hinter dem Flag für experimentelle Web-Plattform-Funktionen an. Das Dokument besagt:

This specification defines 'anchor positioning', where a positioned element can size and position itself relative to one or more "anchor elements" elsewhere on the page.

In meinen Demos habe ich die Anker-Positionierung verwendet, um den Tooltip und die Menüfelder neben ihren Toggle-Schaltflächen zu platzieren. Sehen wir uns an, wie wir Anker definieren und sie im CSS-Code referenzieren können.

Wie ihr ein Anker-Element definiert

Es gibt zwei verschiedene Wege, um Anker zu definieren. Ihr könnt ein HTML-Element in einen Anker verwandeln, indem ihr dem Element eine id zuweist, und dann das anchor-Attribut verwendet, um ein anderes Element an diesen Anker zu binden. Hier ist ein Beispiel in Kombination mit einem Popover:

<button id="toggle-btn-1" popovertarget="popover-1" class="toggle-btn"> Info </button> <div id="popover-1" popover anchor="toggle-btn-1"> Hi, I'm a popover! </div>

Alternativ könnt ihr die CSS-Eigenschaft anchor-name verwenden, um einen Anker zu definieren. Diese Eigenschaft akzeptiert einen dashed-ident Wert wie etwa --toggle-btn. Anschließend nutzt ihr die Eigenschaft position-anchor, um ein anderes Element an den Anker zu binden.

button.toggle-btn { anchor-name: --toggle-btn; } div[popover] { position-anchor: --toggle-btn; }

Inhalte mit der anchor() Funktion positionieren

Gut, ihr habt jetzt ein HTML-Element als Anker definiert und ein Popover daran gebunden. Jetzt könnt ihr die Funktion anchor() verwenden, um das Popover zu positionieren. Die Funktion akzeptiert drei Argumente:

  • Anker-Element: Dieser Wert gibt an, wo sich das Anker-Element befindet. Ihr könnt einen expliziten Ankernamen angeben. Oder ihr lasst den Wert weg, um den impliziten Anker zu verwenden, der über das Attribut anchor oder die CSS-Eigenschaft position-anchor definiert wurde.
  • Verankerungs-Seite: Dieser Wert bezieht sich auf die Position der entsprechenden Seite des Anker-Elements. Zum Beispiel: bottom oder left.
  • Fallback (optional): Ein Längen- oder prozentualer Wert, der als Fallback im Falle einer ungültigen Ankerfunktion dient.

Das folgende Beispiel zeigt, wie ihr einen Tooltip unterhalb der Toggle-Schaltfläche platzieren und horizontal zentrieren könnt:

[role="tooltip"][popover] { position: absolute; position-anchor: --toggle-btn; top: anchor(bottom); left: anchor(center); translate: -50% 0; }

Die Spezifikation enthält noch weitere Funktionen wie die Eigenschaft anchor-scroll und die Funktion anchor-size(). Aber der Blog-Beitrag ist schon lang genug, daher bin ich mal so frech und lasse sie aus.

Barrierefreiheit von Popovers

Sind Popovers barrierefrei? Wie meine Beispiele oben zeigen, könnt ihr mit der neuen Popover-API nutzerfreundliche, barrierefreie Komponenten erstellen. Aber das passiert nicht von selbst.

Definiert die passende semantische Rolle

Das popover-Attribut kann die Barrierefreiheit eurer Website auf jeden Fall verbessern. Zum Beispiel durch die Möglichkeit, das Popover mit der ESC-Taste zu schließen. Oder durch die semantische Beziehung zwischen dem Toggle-Button und dem Popover, die durch das Attribut popovertarget erzeugt wird.

Andererseits definiert das popover-Attribut keine implizite Rolle für das HTML-Element, dem es hinzugefügt wird. Das bedeutet: Denkt über euren konkreten Anwendungsfall nach und verwendet dann das passende native HTML-Element oder die angemessene ARIA-Rolle (wie zum Beispiel tooltip oder menu).

Screenreader-Unterstützung

Wie erleben Nutzer:innen von Screenreadern die Interaktion mit Webinhalten, die mit der Popover-API erstellt wurden? Aufgrund der begrenzten Browser-Unterstützung für die neuen Features habe ich meine Demos nur in den folgenden Szenarien getestet:

  1. NVDA 2023.1, Windows 11, Google Chrome Chanary 117.0.5876.0
  2. TalkBack, Samsung Galaxy S20, Android 13, Google Chrome Chanary 117.0.5876.0

Beide Demos haben super funktioniert: Ich konnte mit der Tastatur durch den Tooltip und die Menüs navigieren, während NVDA die semantischen Rollen und den aktuellen Status der Steuerelemente vorlas.

Auch die Interaktion auf meinem Smartphone verlief reibungslos: Bei aktiviertem TalkBack navigierte ich mit Wischgesten durch die Seiten, während der Screenreader mich über den Inhalt, die semantischen Rollen und den aktuellen Status der Bedienelemente informierte.

Das stimmt mich wirklich optimistisch für die Zukunft des Webs! Ich werde noch weitere Tests mit anderen Browsern und Screenreadern durchführen, sobald die Popover-API besser unterstützt wird.

Browser-Unterstützung

Wann können wir die Popover-API und CSS Anchor Positioning produktiv einsetzen? Leider wird es noch einige Zeit dauern, bis es eine browserübergreifende Unterstützung für diese Features geben wird.

Laut caniuse.com wird das popover Attribut bereits von Chrome und Edge unterstützt. In der Safari 17 Technology Preview wird das Attribut angekündigt, während Firefox es nur als experimentelles Feature anführt (ihr müsst das dom.element.popover.enabled Flag setzen).

Die browserübergreifende Unterstützung für CSS Anchor Positioning wird wohl noch länger dauern. Soweit ich weiß hat bisher nur Chrome das experimentelle Feature implementiert. Aufgrund des Status als „First Public Working Draft“ kann sich die aktuelle Spezifikation in Zukunft noch ändern. Wir müssen einfach abwarten und sehen was passiert.

Fazit

Die neue Popover-API in Kombination mit CSS Anchor Positioning wird unser Leben als Web-Entwickler:innen einfacher machen und zu mehr Barrierefreiheit im Web beitragen.

Trotz des noch experimentellen Status der neuen APIs solltet ihr sie selbst ausprobieren und euch mit den neuen Attributen und Eigenschaften vertraut machen. Auf diese Weise seid ihr dann schon startklar, wenn die Features endlich von allen modernen Browsern unterstützt werden. 😎

Nützliche Links

Update am 05.04.2024

Code-Beispiele und Erläuterungen überarbeitet, um der aktualisierten CSS Anchor Positioning Spezifikation (W3C Working Draft, 26. März 2024) sowie der Implementierung in Chrome Canary zu entsprechen.

Erstellt am