Zurück zum Blog
Aug. 2026·3 Min. LesezeitKI-generiert
Sprache:DeutschEnglishFrançaisÖsterreichischKlingonisch Originalfassung: English

Grundlagen der Barrierefreiheit: ARIA ohne Rätselraten

#accessibility#html#frontend

Der häufigste ARIA-Fehler ist nicht, das falsche Attribut zu verwenden – sondern überhaupt zu ARIA zu greifen, wenn ein natives HTML-Element das Problem gratis gelöst hätte. ARIA (Accessible Rich Internet Applications) gibt es, um eigene Widgets zu beschreiben, für die HTML kein eingebautes Element hat, nicht um ein <div> aufzupäppeln, das für einen <button> einsteht. Die erste Regel von ARIA, direkt von den Autoren der Spezifikation, lautet: Verwende kein ARIA, wenn du nicht musst.

Das Div-Button-Problem

Das taucht ständig in Komponentenbibliotheken auf:

<div class="button" onclick="submitForm()">Submit</div>

Optisch ist es ein Button. Für einen Screenreader ist es ein unbeschrifteter, nicht interaktiver Textblock – nicht per Tab fokussierbar, nicht als Button angekündigt, nicht per Enter oder Leertaste aktivierbar. All das lässt sich mit ARIA und JavaScript nachrüsten:

<div
  class="button"
  role="button"
  tabindex="0"
  onclick="submitForm()"
  onkeydown="if (event.key === 'Enter' || event.key === ' ') submitForm()"
>
  Submit
</div>

Oder man nimmt das Element, das all das bereits kann:

<button onclick="submitForm()">Submit</button>

Tastaturunterstützung, Fokusbehandlung, der zugängliche Name, die korrekte Rolle – alles gratis, alles konsistent über jeden Browser und Screenreader, null JavaScript nötig. Das ist das Muster, das man verinnerlichen sollte: Greife zuerst zu <button>, <a href>, <input>, <select> und Co. und verlasse die native Semantik von HTML nur, wenn du etwas baust, wofür HTML wirklich kein Element hat, etwa ein Tab-Panel oder eine Combobox mit Autovervollständigung.

Wann ARIA seinen Platz verdient: Beschriftung

Selbst bei nativen Elementen brauchen manche Dinge zusätzlichen Kontext, den sichtbarer Text nicht vermittelt. Ein Button nur mit Icon ist der klassische Fall:

<button aria-label="Close dialog">
  <svg><!-- X icon --></svg>
</button>

Ohne aria-label kündigt ein Screenreader das nur als „Button" an – technisch fokussierbar und aktivierbar, aber der Nutzer hat keine Ahnung, was er tut. aria-label liefert einen zugänglichen Namen, wenn es keinen sichtbaren Text gibt, der ihn liefern könnte. Gibt es sichtbaren Text in der Nähe, der nicht im Button selbst steht, verweist aria-labelledby per ID darauf, statt ihn zu duplizieren:

<h2 id="billing-heading">Billing Address</h2>
<button aria-labelledby="billing-heading">Edit</button>

Das wird als „Edit, Billing Address" angekündigt – nützlicher als ein bloßes „Edit", wenn eine Seite fünf identische Bearbeiten-Buttons für fünf verschiedene Abschnitte hat.

Zustand auf eigenen Widgets beschreiben

Hier leistet ARIA echte, tragende Arbeit: Eigene Komponenten müssen Zustandsänderungen ankündigen, die native Elemente automatisch behandeln. Ein einklappbarer Abschnitt:

<button aria-expanded="false" aria-controls="panel-1" id="toggle-1">
  Show details
</button>
<div id="panel-1" hidden>
  ...
</div>
const toggle = document.getElementById('toggle-1');
const panel = document.getElementById('panel-1');

toggle.addEventListener('click', () => {
  const isExpanded = toggle.getAttribute('aria-expanded') === 'true';
  toggle.setAttribute('aria-expanded', String(!isExpanded));
  panel.hidden = isExpanded;
});

aria-expanded muss in JavaScript mit dem tatsächlich sichtbaren Zustand synchron gehalten werden – ARIA-Attribute tun von sich aus nie etwas, sie sind rein informativ für assistive Technologien. Setzt man aria-expanded="false" und aktualisiert es nie, wird einem Screenreader-Nutzer für immer gesagt, das Panel sei eingeklappt, selbst nachdem er es geöffnet hat.

Live-Regionen für dynamische Aktualisierungen

Ändert sich Inhalt ohne Seitennavigation oder Fokuswechsel – eine Formularvalidierungsmeldung erscheint, ein „Gespeichert"-Toast, Suchergebnisse aktualisieren sich –, sehen sehende Nutzer das, aber ein Screenreader hat keinen Grund, etwas außerhalb des aktuellen Fokus des Nutzers anzukündigen, sofern man es ihm nicht sagt.

<div aria-live="polite" id="save-status"></div>
document.getElementById('save-status').textContent = 'Changes saved.';

aria-live="polite" sagt der assistiven Technologie, die Änderung anzukündigen, sobald der Nutzer innehält, womit auch immer er gerade beschäftigt ist – angemessen für Statusmeldungen. Verwende aria-live="assertive" nur für Dinge, die wirklich unterbrechen müssen, etwa eine Warnung zum Ablauf der Sitzung; übermäßiger Einsatz macht eine Seite mit Screenreader anstrengend, weil jedes kleine Update abbricht, was gerade vorgelesen wurde.

Die Regel, die die meisten Bugs abfängt

Wenn du nur eine Gewohnheit mitnimmst: Frage dich nach dem Hinzufügen jedes role- oder aria-*-Attributs, welches native Element die Notwendigkeit hätte vermeiden können. role="button" auf einem <div> → hätte <button> sein sollen. role="navigation" auf einem generischen Wrapper → hätte <nav> sein sollen. aria-required="true" auf einem Texteingabefeld → hätte das Attribut required sein sollen, das dasselbe an assistive Technik vermittelt und obendrein kostenlose Validierung im Browser liefert.

Dann, für das ARIA, das du behältst: Lass es einmal durch einen Screenreader laufen. VoiceOver ist auf jedem Mac vorinstalliert (Cmd+F5 zum Umschalten), und NVDA ist unter Windows kostenlos. Fünf Minuten, die eigene Oberfläche per Tastatur und Gehör zu navigieren, fangen mehr echte Probleme ab, als die ARIA-Spezifikation von vorn bis hinten zu lesen – man bemerkt sofort einen unbeschrifteten Icon-Button oder eine Live-Region, die nie feuert, weil man selbst derjenige ist, der von der Stille verwirrt wird.

Fazit

ARIA ergänzt die Semantik von HTML für die Fälle, die HTML nicht abdeckt – es ersetzt nicht, von vornherein das richtige Element zu verwenden. Beginne mit nativem HTML, füge aria-label/aria-labelledby hinzu, wo der zugängliche Name aus sichtbarem Text nicht offensichtlich ist, verwende Zustandsattribute wie aria-expanded nur, wenn du sie auch mit der Realität synchron hältst, und reserviere Live-Regionen für Aktualisierungen, die ein Nutzer außerhalb seines aktuellen Fokus wirklich hören muss.

NeuerEin einfaches Kommandozeilen-Tool in Node.js schreibenÄlterEin praktischer Leitfaden zu Git-Branching-Strategien