ARIA hilft nur, wenn du es kaum benutzt
Es gibt zwei Wege, ein Kontrollkästchen auf einer Seite zu bauen, und beide kommen durch die üblichen automatischen Prüfungen. Der eine braucht vier ARIA-Attribute, einen tabindex und ein paar Zeilen JavaScript. Der andere braucht eine Zeile HTML.
Dasselbe Kästchen, zweimal gebaut
<!-- Fassung A: nachgebaut -->
<div role="checkbox"
aria-checked="false"
aria-labelledby="nl-text"
aria-required="true"
tabindex="0">
<span id="nl-text">Newsletter abonnieren</span>
</div>
<!-- dazu kommen noch Handler für Klick und Leertaste -->
<!-- Fassung B: dasselbe in einer Zeile -->
<label><input type="checkbox" name="newsletter" required> Newsletter abonnieren</label>
Ein Screenreader sagt bei beiden Fassungen dasselbe an, nämlich ein verpflichtendes Kontrollkästchen mit der Beschriftung Newsletter abonnieren. Bedienen lässt sich nur eine davon. Fassung A reagiert auf gar nichts, solange niemand den Klick, die Leertaste und das Umschalten von aria-checked in JavaScript nachbaut. Fehlt die Leertaste, hört jemand mit Screenreader weiterhin "Kontrollkästchen, nicht angehakt" und kommt trotzdem nicht weiter. Fassung B bringt Tastaturbedienung, Fokus, Zustand, die anklickbare Beschriftung und die Formularübertragung von sich aus mit.
Der übliche Grund für Fassung A ist die Optik. Früher ließen sich Kontrollkästchen kaum gestalten, also hat man sie aus divs nachgebaut. Das gilt seit Jahren nicht mehr. Ein natives Kästchen lässt sich mit accent-color einfärben, und wer mehr will, setzt appearance: none und zeichnet Rahmen, Hintergrund und Haken selbst über :checked und :focus-visible. Das Element bleibt dabei ein echtes input, die Bedienlogik bleibt erhalten, und du sparst dir den gesamten ARIA-Aufbau.
Was ARIA tut und was es nicht tut
ARIA ist eine Sammlung von Attributen, mit denen du dem Browser sagst, wie er ein Element an Hilfsmittel weiterreichen soll. Der Browser pflegt neben dem sichtbaren Seitenaufbau ohnehin einen zweiten, unsichtbaren Baum, aus dem Screenreader, Braillezeilen und Sprachsteuerung ihre Angaben ziehen, und ARIA ändert Einträge in genau diesem Baum. ARIA schreibt also am Schild, das an einem Element hängt.
An der Maschine hinter dem Schild ändert sich dabei nichts. Ein role="button" erzeugt keinen Tastaturfokus. Ein aria-checked hakt nichts an. Ein aria-expanded klappt nichts auf. Ein aria-disabled hindert niemanden am Absenden. Jedes Verhalten, das ein natives Element mitbringt, musst du bei einem nachgebauten Element selbst schreiben, und zwar vollständig, inklusive Enter, Leertaste, Pfeiltasten und Escape.
Daraus folgt die bekannteste Faustregel im Umgang mit ARIA. Wenn ein HTML-Element die Aufgabe schon erledigt, nimm das HTML-Element. Kein role ist immer noch besser als ein falsches. Das klingt streng, spart dir aber die gesamte Tastaturlogik, die sonst dein Problem wird.
Drei Fehlgriffe, die auf echten Seiten stehen
Die folgenden drei Muster tauchen auf kleinen Seiten immer wieder auf, meist im Burger-Menü, im Cookie-Hinweis, in Produktfiltern und in Bildergalerien. Alle drei stammen aus guter Absicht, und alle drei kosten mehr, als sie bringen.
Der Knopf, der keiner ist
<!-- vorher -->
<div role="button" onclick="menueOeffnen()">Menü</div>
<!-- nachher -->
<button type="button" onclick="menueOeffnen()">Menü</button>
Die obere Zeile wird als Schaltfläche angesagt, bekommt aber ohne tabindex="0" nie den Fokus, und selbst mit Fokus reagiert sie weder auf Enter noch auf die Leertaste, weil ein onclick am div nur auf Mausklicks hört. Wer mit der Tastatur oder mit Sprachsteuerung arbeitet, kommt an diesem Menü nicht vorbei. Die untere Zeile macht alles davon von allein.
Das aria-label, das den sichtbaren Text überschreibt
<!-- vorher -->
<a href="/preise" aria-label="Hier klicken">Preise und Pakete</a>
<!-- nachher -->
<a href="/preise">Preise und Pakete</a>
Ein aria-label ersetzt den sichtbaren Text vollständig. Der Screenreader liest "Hier klicken" vor, und wer den Link per Sprachbefehl ansteuert, sagt "Klick Preise und Pakete" und löst damit nichts aus, weil der Name im Barrierebaum ein anderer ist als der Name auf dem Bildschirm. Sichtbare Beschriftung und angesagter Name sollten übereinstimmen, und wenn der sichtbare Text schon aussagekräftig ist, brauchst du gar kein Label.
Das aria-hidden über etwas Bedienbarem
<!-- vorher -->
<div class="teaser" aria-hidden="true">
<a href="/kontakt">Termin vereinbaren</a>
</div>
<!-- nachher -->
<div class="teaser">
<a href="/kontakt">Termin vereinbaren</a>
</div>
Das Attribut nimmt einen Bereich samt allem darin aus dem Barrierebaum heraus, hält den Tastaturfokus aber nicht auf. Der Fokus wandert weiter in den Link hinein, und dort sagt der Screenreader nichts an, weil es aus seiner Sicht nichts mehr gibt. Das ist die unangenehmste Sorte Fehler, weil der Rahmen mitten auf der Seite verschwindet und niemand sagen kann, wo er gerade steht. aria-hidden gehört auf dekorative Dinge ohne Fokus, etwa auf ein Icon neben einem Text, der dasselbe schon sagt.
Wann ARIA seinen Job macht
Sobald du etwas baust, für das HTML kein Element hat, brauchst du ARIA wirklich. Ein Akkordeon ist der häufigste Fall auf kleinen Seiten. HTML kennt zwar details und summary, aber wer eigenes Aufklappen mit Animation baut, muss den Zustand ansagen.
<button type="button" aria-expanded="false" aria-controls="faq-1">
Wie lange dauert der Einbau?
</button>
<div id="faq-1" hidden>
<p>Etwa zehn Minuten, das Skript kommt in den Kopfbereich der Seite.</p>
</div>
Hier steht ARIA auf einem echten button, der Fokus, Enter und Leertaste schon mitbringt. Dein JavaScript setzt beim Klick aria-expanded auf true und entfernt hidden, und der Screenreader sagt "erweitert" statt "reduziert". Genauso berechtigt ist role="status" auf einem Absatz, in den du Meldungen schreibst, etwa "Nachricht gesendet". Ändert sich der Text darin, wird er vorgelesen, ohne dass der Fokus springt. Wichtig ist nur, dass der Absatz von Anfang an im Quelltext steht, sonst bemerkt der Screenreader die Änderung nicht. Beides sind Ansagen über etwas, das HTML nicht ausdrücken kann, und genau dort liegt der Zweck von ARIA.
Warum ein falsches Attribut schlechter ist als keins
Ohne ARIA hört jemand bei einem angeklickten div gar nichts und weiß, dass da nichts ist. Mit einem falschen role hört er eine Zusage, die die Seite nicht einlöst, und sucht den Fehler bei sich. Er drückt Enter, wartet, drückt nochmal, hält seine Software für kaputt und geht. Dazu kommt, dass ein falsches role die eingebaute Bedeutung überschreibt. Ein <a role="button"> taucht nicht mehr in der Linkliste des Screenreaders auf, obwohl es zu einer anderen Seite führt. Prüfprogramme melden solche Stellen häufig nicht, weil formal ein gültiges Attribut dasteht.
Zwei Minuten Selbsttest
- Öffne deine Startseite und schieb die Maus weg.
- Drücke Tab, bis der Rahmen auf dem ersten Ding steht, das nach Knopf, Menü oder Filter aussieht.
- Drücke Enter. Passiert nichts, drücke die Leertaste.
- Reagiert das Element auf keine der beiden Tasten, ist es kein Knopf, egal was im Quelltext steht. Notiere die Stelle.
- Tabbe weiter durch Navigation, Akkordeon, Bildergalerie und Formular und achte darauf, ob der Rahmen irgendwo unsichtbar wird oder hängen bleibt.
- Zähle am Ende die notierten Stellen. Jede davon ist ein Element, das ein natives
button,aoderinputsein sollte.
Der Handgriff für den Zweifelsfall
Wenn du in deinem Quelltext auf ein ARIA-Attribut stößt und nicht mehr weißt, warum es dort steht, lösche es probeweise und bediene die Stelle mit der Tastatur. In den meisten Fällen bleibt alles, wie es war, und du bist eine Zeile los, die du sonst pflegen müsstest. Bricht dagegen etwas weg, hast du eine Stelle gefunden, an der die Ansage tatsächlich getragen hat, und kannst sie mit gutem Gewissen stehen lassen. Nimm dir dafür die vier oder fünf Attribute vor, die in deinem Code am häufigsten vorkommen, dann hast du den größten Teil in einer halben Stunde geklärt.
Ist deine Website barrierefrei? Der Schnelltest prüft deine Startseite in unter einer Minute und zeigt dir, wo es hakt. Ohne Anmeldung.
Seite kostenlos prüfen