Frontend-Barrierefreiheit (Accessibility)
Gilt für Komponenten in <ui-packages-dir> und Seiten in <web-dir>/src/. Ziel ist WCAG 2.1 Level AA – dies ist eine Untergrenze, nicht ein Ziel.
Projektkonventionen auflösen
Werte in spitzen Klammern stammen aus dem Stack-Profil des Projekts. Lösen Sie sie in dieser Reihenfolge auf:
- Lesen Sie
STACK-PROFILE.mdim Repository-Stammverzeichnis und verwenden Sie dessen Werte wörtlich. - Wenn die Datei fehlt oder ein Schlüssel fehlt, leiten Sie die Werte aus dem Repository ab –
css-strategyundui-frameworkaus den Abhängigkeiten der Webanwendung. - Wenn noch nicht aufgelöst, orientieren Sie sich an der im Repository vorherrschenden Konvention.
- Nur wenn das Repository leer ist, greifen Sie auf die in dieser Fertigkeit angegebenen Standardwerte zurück – schreiben Sie die gewählten Werte dann in
STACK-PROFILE.md.
Erfinden Sie niemals eine neue Konvention, wenn das Repository bereits eine vorgibt.
Harte Regeln
1. Semantisches HTML zuerst
<button>für Aktionen,<a>für Navigation. Niemals ein<div>mit einem Klick-Handler.- Überschriften-Ebenen absteigend ohne Sprünge.
- Jedes Formularfeld mit
<label>verknüpft überhtmlFor. - Gruppierte Steuerelemente mit
<fieldset>und<legend>. - Auf jeder Seite:
<nav>,<main>,<footer>,<aside>.
2. ARIA nur dort, wo HTML nicht ausreicht
Die Reihenfolge der Bevorzugung ist: semantisches Element, dann ARIA-Attribut, dann benutzerdefiniertes Verhalten. Verwenden Sie ARIA niemals, um die Semantik eines vorhandenen Elements zu überschreiben – ein role="button" auf einem <div> implementiert schlecht nach, was <button> kostenlos bietet.
Falsches ARIA ist schlimmer als keines: Ein falsches aria-label ersetzt stillschweigend den zugänglichen Namen, den ein Screenreader sonst korrekt berechnen würde.
3. Tastaturbedienung ist Pflicht
- Alles Interaktive ist mit Tab erreichbar.
- Die Tab-Reihenfolge folgt der visuellen Reihenfolge.
- Der Fokus ist immer sichtbar. Entfernen Sie niemals einen Outline, ohne ihn zu ersetzen.
Escapeschließt Dialoge und Popover;EnterundLeertasteaktivieren Steuerelemente; Pfeiltasten bewegen sich innerhalb zusammengesetzter Widgets.- Benutzerdefinierte Widgets verwalten den Fokus explizit.
4. Farbe und Kontrast
- 4,5:1 für normalen Text, 3:1 für großen Text (18px oder 14px fett) und für bedeutungsvolle UI-Grenzen.
- Farbe trägt niemals allein eine Bedeutung – kombinieren Sie sie mit Text, einem Symbol oder einem Muster.
- Beide Themes werden überprüft, nicht nur das Standard-Theme.
5. Bilder und Medien
- Jedes Bild hat
alt. Beschreibend für Inhalte,alt=""für Dekoration. - Niemals „Bild", „Foto" oder der Dateiname.
- Komplexe Bilder erhalten eine lange Beschreibung über
aria-describedbyoder eine Bildunterschrift. - Video enthält Untertitel; Audio enthält ein Transkript.
6. Formulare
- Jede Eingabe beschriftet.
- Fehler mit
aria-describedbyverknüpft und mitrole="alert"angesagt. - Ungültige Felder mit
aria-invalidmarkiert. - Pflichtfelder mit dem
required-Attribut markiert – und wenn ein Sternchen angezeigt wird, muss seine Bedeutung irgendwo im Text erklärt werden. - Bei fehlgeschlagenem Senden wird der Fokus auf das erste ungültige Feld gesetzt.
7. Zielgröße
WCAG 2.1 AA hat keine Mindestzielgröße (2.2 AA legt 24×24 CSS-Pixel fest; die 44×44-Angabe stammt aus 2.1 AAA und der Plattform-HIG-Konvention). Behandeln Sie 44×44 als Untergrenze für primäre Aktionen auf Touch-Oberflächen und wenden Sie es wie folgt an:
- Primäre und destruktive Aktionen sowie alles, was ein Benutzer auf einem Telefon erreicht: 44×44.
- Dichte Desktop-Oberflächen – Symbolleisten, Tabellenzeilenaktionen, kompakte Formularsteuerelemente – können kleiner sein, bis zu 24×24, sofern die Ziele nicht neben anderen Zielen liegen und eine gleichwertige vollgroße Steuerung an anderer Stelle existiert.
- Abstände zählen. Ein 32px-Steuerelement mit 6px Freiraum auf jeder Seite erfüllt das 2.2-Kriterium; ein 32px-Steuerelement, das direkt neben seinem Nachbarn liegt, nicht.
Bezogene Komponentenbibliotheken liegen typischerweise unter dieser Untergrenze – eine Standard-Schaltflächenhöhe von 32 oder 36 CSS-Pixel ist üblich. Bearbeiten Sie die bezogene Datei nicht von Hand, um dies zu korrigieren, und behandeln Sie die Abweichung nicht als standardmäßig akzeptabel. Erhöhen Sie die Vorgabe in <wrappers-pkg>, sodass jeder Konsument die konforme Größe erbt, und halten Sie die kleineren Größen als explizite Opt-Ins für dichte Kontexte verfügbar. Auf diese Weise ist die barrierefreie Wahl diejenige, die Sie erhalten, wenn Sie nicht darüber nachdenken.
Halten Sie in STACK-PROFILE.md fest, für welche Lösung sich das Projekt entschieden hat. Ein nicht dokumentierter Verzicht wird alle sechs Monate als Fehler wiederentdeckt.
8. Bewegung
- Respektieren Sie
prefers-reduced-motion. - Automatisch abgespielte Inhalte haben eine Pause-Steuerung.
- Nichts blinkt mehr als dreimal pro Sekunde.
9. Testen ist Teil der Arbeit
- Bedienen Sie die Funktion nur mit der Tastatur.
- Hören Sie sie mit einem Screenreader – VoiceOver auf macOS, NVDA auf Windows.
- Führen Sie einen automatisierten Scan in der End-to-End-Suite durch.
Automatisierte Tools erkennen etwa ein Drittel der tatsächlichen Probleme. Sie sind eine Untergrenze, kein Freibrief.
Muster (Patterns)
Vollständige Implementierungen befinden sich in references/component-patterns.md. Was jedes Muster garantiert:
- Button – Ein semantischer
<button>, dessen Fokusring für Tastaturbenutzer sichtbar ist, aber nicht bei Mausklicks (focus-visible), mit bewegungssicheren Übergängen und einerariaLabel-Eigenschaft für die Verwendung nur mit Symbolen. - Formular-Eingabe – Eine beschriftete Eingabe, deren Fehlertext programmatisch mit
aria-describedbyverknüpft, mitrole="alert"angesagt und mitaria-invalidgekennzeichnet ist; das erforderliche Sternchen istaria-hidden. - Dialog – Ein nativer
<dialog>, dershowModal()für kostenlosen Fokus-Einfang,Escape-Behandlung und inaktiven Hintergrund verwendet; der Fokus wird beim Öffnen hineingesetzt und beim Schließen auf das auslösende Element zurückgesetzt. - Listbox – Eine benutzerdefinierte Auswahl mit wandernder Pfeiltasten-Navigation und korrekter ARIA-Verkabelung (
aria-activedescendant,role="listbox"); bauen Sie dies nur, wenn ein natives<select>nicht passt. - Skip-Link – Ermöglicht Tastaturbenutzern, die Navigation zu überspringen, nur bei Fokus sichtbar; das Ziel trägt
tabIndex={-1}, sodass der Fokus tatsächlich dort ankommt.
WCAG-Kurzreferenz
| Prinzip | Anforderung | In der Praxis |
|---|---|---|
| Wahrnehmbar | Inhalt für jeden Sinn verfügbar | Alternativtext, Untertitel, Farbe plus Symbol |
| Bedienbar | Alles mit der Tastatur erreichbar | Tab-Reihenfolge, Escape schließt, Fokus sichtbar |
| Verständlich | Vorhersehbar, klar formuliert | Konsistente Navigation, einfache Sprache |
| Robust | Funktioniert mit Hilfstechnologien | Gültiges HTML, korrektes ARIA, semantische Elemente |
| Problem | Lösung |
|---|---|
| Unbeschriftete Eingabe | <label htmlFor> hinzufügen |
| Niedriger Kontrast | 4,5:1 erreichen, oder 3:1 für großen Text |
| Kein Tastaturpfad | Echte interaktive Elemente, verwalteter Fokus |
| Fehlender Alternativtext | Beschreiben, oder alt="" wenn dekorativ |
| Farbe als einzige Bedeutung | Text oder Symbol hinzufügen |
| Symbol-Only-Button | aria-label hinzufügen |
| Blinkender Inhalt | Weniger als drei Blitze pro Sekunde |
Bewegungseinstellungen
Behandeln Sie reduzierte Bewegung in reinem CSS. Eine Utility-Klassen-Variante wie motion-safe: gilt nur, wenn Bewegung erlaubt ist. Wenn Sie sie in eine Reduzierte-Bewegung-Abfrage setzen, erhalten Sie eine Regel, die niemals zutreffen kann.
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Nahe Null statt none sorgt dafür, dass Übergangs-End-Ereignisse ausgelöst werden, sodass Komponenten, die darauf warten, nicht hängen bleiben.
Für die Steuerung pro Komponente wenden Sie die Variante motion-safe: auf die animierte Utility selbst an – motion-safe:transition-colors, wie beim obigen Button.
Visuell versteckter Inhalt
Die meisten Utility-Frameworks liefern bereits sr-only und not-sr-only. Verwenden Sie diese; definieren Sie sie nicht neu. Wenn Ihres keines hat, befindet sich die Referenzimplementierung in references/component-patterns.md.
Test-Checkliste
Tastatur
- Jedes interaktive Element mit Tab erreichbar
- Tab-Reihenfolge entspricht visueller Reihenfolge
- Fokus immer sichtbar
- Escape schließt Dialoge und Popover
- Pfeiltasten funktionieren in zusammengesetzten Widgets
- Fokus kehrt zum Auslöser zurück, wenn ein Dialog geschlossen wird
Screenreader
- Alle Inhalte erreichbar
- Steuerungszwecke ohne umgebenden Kontext klar
- Labels werden mit ihren Feldern angesagt
- Fehler werden über
role="alert"angesagt - Landmarken vorhanden
- Dekorative Elemente mit
aria-hiddenversteckt
Farbe
- 4,5:1 normaler Text, 3:1 großer Text und UI-Grenzen
- Keine Bedeutung nur durch Farbe
- Beide Themes überprüft
Bewegung
- Reduzierte Bewegung wird respektiert
- Kein Blinken mehr als dreimal pro Sekunde
- Automatisch abgespielte Inhalte können pausiert werden
Automatisiert
Scans werden innerhalb der Playwright-Suite ausgeführt – siehe frontend-testing. Der Axe-in-Playwright-Ausschnitt befindet sich in references/component-patterns.md.
Referenzdokumente
| Vertiefung | Referenz |
|---|---|
| Barrierefreie Komponentenimplementierungen: Button, Formular-Eingabe, Modal, Listbox, Skip-Link | references/component-patterns.md |
Verwandte Fertigkeiten
frontend-architecture– Komponentenschichtung und Themingfrontend-testing– wo diese Prüfungen ausgeführt werdenfrontend-component-docs– Dokumentation des Barrierefreiheitsvertrags einer Komponente