Kurz erklärt
ARIA (Accessible Rich Internet Applications) ist ein W3C-Standard, der HTML-Attribute bereitstellt, um moderne Web-Interfaces für Assistenztechnologien zugänglich zu machen. ARIA fügt semantische Informationen hinzu, die Standard-HTML nicht bietet – besonders für Custom Widgets wie Tabs, Accordions, Dialoge und dynamische Updates.
Die ARIA-Grundregel: “No ARIA is better than bad ARIA”
Erste Regel: Verwende natives HTML, wenn möglich
- ✓
<button> statt <div role="button">
- ✓
<nav> statt <div role="navigation">
- ✓
<input type="checkbox"> statt Custom Toggle
Zweite Regel: ARIA ändert nur Accessibility Tree, nicht Verhalten
- ARIA macht
<div role="button"> nicht klickbar
- ARIA macht
<div role="link"> nicht navigierbar
- JavaScript für Verhalten ist trotzdem nötig
Dritte Regel: Falsch verwendetes ARIA ist schlimmer als gar keins
- Widersprüchliche Rollen verwirren Screenreader
- Falsches
aria-label gibt falsche Informationen
Die drei ARIA-Säulen
1. Roles – Was ist dieses Element?
Landmark Roles (Orientierung auf der Seite):
<header role="banner">Kopfbereich</header>
<nav role="navigation">Hauptnavigation</nav>
<main role="main">Hauptinhalt</main>
<aside role="complementary">Seitenleiste</aside>
<footer role="contentinfo">Fußzeile</footer>
Widget Roles (interaktive Elemente):
<div role="button" tabindex="0">Custom Button</div>
<div role="tab" aria-selected="true">Tab 1</div>
<div role="dialog" aria-modal="true">Modal-Dialog</div>
<div role="alert">Wichtige Nachricht</div>
Document Roles (Strukturierung):
<article role="article">Artikel-Inhalt</article>
<section role="region" aria-labelledby="heading">Bereich</section>
aria-label – Beschreibung für Screenreader (überschreibt sichtbaren Text):
<button aria-label="Schließen">×</button>
<a href="/cart" aria-label="Warenkorb, 3 Artikel">🛒</a>
aria-labelledby – Referenz zu anderem Element für Beschreibung:
<h2 id="dialog-title">Bestätigung erforderlich</h2>
<div role="dialog" aria-labelledby="dialog-title">...</div>
aria-describedby – Zusätzliche Beschreibung/Hilfetext:
<input
type="email"
aria-describedby="email-help"
>
<span id="email-help">Wir versenden keine Spam-Mails</span>
aria-hidden – Element vor Screenreadern verstecken:
<span aria-hidden="true">🎉</span> <!-- Dekoratives Icon -->
aria-expanded – Zustand von Accordion/Dropdown:
<button aria-expanded="false" aria-controls="menu">
Menü
</button>
<ul id="menu" hidden>...</ul>
aria-selected – Ausgewähltes Tab/Option:
<div role="tab" aria-selected="true">Tab 1</div>
<div role="tab" aria-selected="false">Tab 2</div>
aria-disabled – Deaktivierter Zustand (visuell + für Screenreader):
<button aria-disabled="true">Speichern</button>
3. Live Regions – Dynamische Updates ankündigen
aria-live – Änderungen ankündigen:
<!-- Sofort unterbrechen -->
<div aria-live="assertive" role="alert">
Fehler beim Speichern!
</div>
<!-- Höflich warten -->
<div aria-live="polite">
Neue Nachricht von Max
</div>
<!-- Nicht ankündigen (Standard) -->
<div aria-live="off">...</div>
role=“alert” – Wichtige Nachricht (automatisch aria-live=“assertive”):
<div role="alert">Formular erfolgreich gesendet!</div>
role=“status” – Status-Update (automatisch aria-live=“polite”):
<div role="status">Artikel zum Warenkorb hinzugefügt</div>
Häufige ARIA-Patterns
<div
role="button"
tabindex="0"
aria-pressed="false"
onclick="toggle()"
onkeypress="handleKey(event)"
>
Toggle Dark Mode
</div>
Wichtig: Tastatur-Support (Enter, Space) muss per JavaScript implementiert werden!
Modal-Dialog
<div
role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
>
<h2 id="dialog-title">Bestätigung</h2>
<p>Möchten Sie wirklich löschen?</p>
<button>Ja</button>
<button>Abbrechen</button>
</div>
Tab-Interface
<div role="tablist" aria-label="Produkt-Informationen">
<button role="tab" aria-selected="true" aria-controls="panel1">
Beschreibung
</button>
<button role="tab" aria-selected="false" aria-controls="panel2">
Bewertungen
</button>
</div>
<div id="panel1" role="tabpanel" aria-labelledby="tab1">
Produkt-Beschreibung...
</div>
<div id="panel2" role="tabpanel" aria-labelledby="tab2" hidden>
Bewertungen...
</div>
<label for="email">E-Mail</label>
<input
type="email"
id="email"
aria-required="true"
aria-invalid="true"
aria-describedby="email-error"
>
<span id="email-error" role="alert">
Bitte gültige E-Mail-Adresse eingeben
</span>
Häufige ARIA-Fehler
❌ Redundante Rollen: <button role="button"> (überflüssig)
❌ Fehlende Tastaturbedienung: <div role="button"> ohne Keyboard-Handler
❌ Widersprüchliche Attribute: <button aria-disabled="true"> aber trotzdem klickbar
❌ aria-label auf Non-Interactive: <div aria-label="..."> ohne role
❌ aria-hidden auf fokussierbaren Elementen: <button aria-hidden="true">
❌ Fehlende aria-labelledby Referenz: ID existiert nicht
ARIA testen
Automatische Tests:
- axe DevTools (Browser-Extension)
- WAVE (WebAIM)
- Pa11y (CI/CD-Integration)
Manuelle Tests:
- NVDA (Windows, kostenlos)
- JAWS (Windows, kommerziell)
- VoiceOver (macOS, iOS, integriert)
- TalkBack (Android)
Browser DevTools:
- Chrome: Elements → Accessibility Tab
- Firefox: Accessibility Inspector
Best Practices
✓ Natives HTML bevorzugen: <button> > <div role="button">
✓ Keyboard-Support implementieren: Tab, Enter, Space, Arrow Keys
✓ aria-label für Icon-Buttons: <button aria-label="Menü öffnen">☰</button>
✓ aria-live für dynamische Inhalte: Chat, Notifications, Validierung
✓ Focus Management: Nach Modal-Öffnung Focus ins Modal setzen
✓ Testen mit echten Screenreadern: Automatische Tests finden nicht alles
Nächste Schritte
- Custom Widgets mit ARIA-Rollen ausstatten (Tabs, Dropdowns, Modals)
- aria-live für dynamische Updates implementieren (Formular-Validierung, Notifications)
- Screenreader-Testing mit NVDA oder VoiceOver durchführen
- axe DevTools installieren und regelmäßig prüfen
- ARIA-Authoring-Practices-Guide konsultieren für komplexe Patterns