Barrierefreie Alerts leicht gemacht mit der Popover API

Benachrichtigungen (Alerts) sind ein gängiges Element auf Websites. Sie lenken die Aufmerksamkeit der Nutzer:innen auf eine wichtige Nachricht, ohne den aktuellen Workflow zu unterbrechen. Zum Beispiel: „Artikel wurde dem Warenkorb hinzugefügt“ oder „Login ist fehlgeschlagen: Prüfen Sie Benutzernamen/Kennwort“.

Dank der neuen Popover API und der neuen Möglichkeiten von CSS-Animationen wird es bald viel einfacher werden, barrierefreie und schön animierte Alerts zu erstellen. Ich habe eine Demo vorbereitet, die ihr ausprobieren könnt.

Ein Mann spricht in ein Megaphon Foto: © Thirdman / pexels.com

Falls ihr mit der Popover API noch nicht vertraut seid, solltet ihr zuerst meinen Artikel „Einfach herausragend! Die neue Popover API und CSS Anchor Positioning“ lesen. Ich werde hier die Grundlagen nicht wiederholen und mich stattdessen auf den speziellen Anwendungsfall konzentrieren.

Barrierefreie Alerts Demo

Hier ist meine Demo für barrierefreie Alerts mit der Popover API. Ihr könnt sowohl die Nachricht als auch die Dauer und Position der Meldung anpassen. Probiert es aus:

Das Alert erscheint über allen anderen Elementen der Seite und wird von Screenreadern automatisch vorgelesen. Ich habe dieses Verhalten mit JAWS, NVDA, TalkBack und VoiceOver. getestet. Die aktuelle Tätigkeit des Nutzers wird nicht unterbrochen und das Alert verschwindet nach einiger Zeit.

Details der Implementierung

Schauen wir uns nun die verschiedenen Bausteine an, mit denen ich die barrierefreien, animierten Alerts gestaltet habe.

Dynamisches HTML erzeugen

Ich habe einen Angular-Service implementiert, der das Popover-Element mit JavaScript-Methoden wie createElement() und appendChild() dynamisch erzeugt. Im Demo-Code findet ihr weitere Details. Ihr müsst nicht mit dem Angular-Framework vertraut sein, um das Wichtigste zu verstehen.

Der folgende HTML-Code wird einem Container am Ende des body-Elements hinzugefügt:

<div popover="manual" role="alert" class="alert top-right"> This is a very important message </div>

Das popover-Attribut verwandelt das div-Element in ein Popover, das zunächst vom Browser ausgeblendet wird. Wir zeigen das Popover-Alert an, indem wir die Methode showPopover() des Elements aufrufen.

Mittels popover="manual" definieren wir einen manuellen Popover-Status für das Element. Damit verhindern wir Light-Dismiss, also das automatische Schließen des Popovers, wenn Nutzer:innen mit anderen Elementen auf der Seite interagieren. Stattdessen schließen wir das Popover programmatisch mit der Methode hidePopover().

Semantisches Markup

Setzt role="alert" auf das Popover-Element, um es als Alert zu definieren. Das Dokument Accessible Rich Internet Applications (WAI-ARIA) 1.2 beschreibt die Alert-Rolle wie folgt:

A type of live region with important, and usually time-sensitive, information. [...] Alerts are assertive live regions, which means they cause immediate notification for assistive technology users.

Im Allgemeinen verwenden wir ARIA-Live-Regionen, um dynamische Inhaltsänderungen zu kommunizieren. Das Setzen von role="alert" hat denselben Effekt wie das Setzen von aria-live="assertive" und aria-atomic="true". Das heißt, Screenreader lesen die Nachricht des Alerts sofort vor, sobald das Popover angezeigt wird.

Animation

Jetzt machen wir noch den visuellen Feinschliff und fügen dem Popover-Element eine Animation hinzu. Es gibt aber ein Problem: Popover werden anfangs durch display: none ausgeblendet. Was für ein Albtraum! Das erzeugt gleich zwei Hindernisse:

  1. Ein Element mit dem Wert none für die display-Eigenschaft wird nicht gerendert. Daher hat es keine berechneten Werte für die verschiedenen CSS-Eigenschaften wie z.B. opacity. Wenn es keinen berechneten Wert gibt, haben wir keinen Ausgangspunkt für die transition.
  2. Das gleiche Problem besteht auch in umgekehrter Richtung: Wenn die Eigenschaft display auf none gesetzt wird, wird das Element sofort aus dem gerenderten HTML-Dokument entfernt, ohne dass der transition-Effekt ausgelöst wird.

Glücklicherweise bietet die CSS Transitions Level 2 Spezifikation neue Möglichkeiten für CSS-Übergänge. Sie definiert die neue @starting-style Regel:

The @starting-style rule is a grouping rule. The style rules inside it are used to establish styles to transition from, if the previous style change event did not establish a before-change style for the element whose styles are being computed.

So können wir einen Ausgangszustand für den Übergang definieren, wenn sich der Anzeigetyp von none zu einem anderen Typ ändert.

Der zweite Puzzlestein ist die neue transition-behavior-Eigenschaft und ihr Wert allow-discrete:

The transition-behavior property specifies whether transitions will be started or not for discrete properties.

Diskrete Eigenschaften haben Werte, die nicht interpoliert werden können. Dies ist z.B. bei den Eigenschaften display und overlay der Fall. Um Übergänge für sie zuzulassen, müssen wir den Wert allow-discrete definieren. Ihr könnt den Wert für transition-behavior auch als Teil einer Shorthand-Deklaration angeben.

Wie passt das nun alles zusammen? Meine Demo enthält die Position "top-right", bei der das Alert langsam sichtbar wird und von rechts in den sichtbaren Bereich rutscht. Hier ist der CSS-Code für den Übergang:

.alert[popover].top-right { /* Final state of the exit animation */ opacity: 0; transform: translateX(100%); transition: opacity 0.5s, transform 0.5s, overlay 0.5s allow-discrete, display 0.5s allow-discrete; } .alert[popover].top-right:popover-open { /* Final state of the show animation */ opacity: 1; transform: translateX(0); } /* Needs to be after the previous [popover]:popover-open rule to take effect, as the specificity is the same */ @starting-style { .alert[popover].top-right:popover-open { opacity: 0; transform: translateX(100%); } }

Im obigen Beispiel werden die Eigenschaften opacity und transform für die Dauer einer halben Sekunde animiert. Wir möchten, dass der Browser den animierten Inhalt anzeigt und das Popover im Top Layer bleibt, solange die Animation läuft. Um dies zu erreichen, definieren wir auch overlay 0.5s allow-discrete und display 0.5s allow-discrete.

Achtung! Diese Funktionen sind experimentell und können sich in Zukunft ändern!

Browser-Unterstützung

Das popover-Attribut wird bereits von allen wichtigen Browsern unterstützt. Zum Zeitpunkt der Erstellung dieses Artikels hatte Firefox die Funktion nur in seinen experimentellen Nightly-Builds aktiviert. Ich erwarte aber, dass Firefox die Funktion bald releast.

Die neuen Funktionen für transition werden derzeit nur von Chrome und Edge unterstützt. Ich hoffe, dass sie Teil der Interop 2024 sein werden und bis Ende des Jahres eine browserübergreifende Kompatibilität erreichen.

Nützliche Links

Erstellt am