ARIA
Die Semantik komplexer Komponenten anreichern, um sie barrierefrei zu machen
Was ist ARIA?
ARIA (Accessible Rich Internet Applications) ist eine W3C-Spezifikation, die es ermöglicht, die Barrierefreiheit von Rich-Web-Anwendungen und dynamischen Komponenten zu verbessern.
🏷️ Rollen
Definieren, was ein Element ist (button, navigation, alert...)
role="button"📊 Zustände
Beschreiben den aktuellen Zustand eines Elements (checked, expanded, disabled...)
aria-expanded="true"🔧 Eigenschaften
Bieten zusätzliche Informationen (label, describedby, controls...)
aria-label="Hauptmenü"⚠️ ARIA Goldene Regel
Verwenden Sie kein ARIA, wenn Sie natives HTML verwenden können
Formulare mit ARIA-Attributen
Schlechtes Beispiel
Formular ohne ARIA
❌ Unzugängliches Formular ohne geeignete ARIA-Attribute:
<!-- Schlecht: kein Label, keine Beschreibung -->
<input type="text" placeholder="Ihre E-Mail">
<!-- Schlecht: Icon nicht barrierefrei -->
<button>
<span class="icon">🔍</span>
</button>
<!-- Schlecht: Fehler nicht zugeordnet, keine Autovervollständigung -->
<input type="password">
<div class="error">Passwort zu kurz</div>Gutes Beispiel
Formular mit ARIA
✅ Barrierefreies Formular mit geeigneten ARIA-Attributen:
<!-- Gut: aria-label für Feld ohne sichtbares Label -->
<input
type="text"
aria-label="E-Mail-Adresse (erforderlich)"
aria-describedby="email-desc"
aria-required="true">
<span id="email-desc">Format: name@beispiel.com</span>
<!-- Gut: Schaltfläche mit aria-label -->
<button aria-label="Formular absenden">
<span aria-hidden="true">🔍</span>
</button>
<!-- Gut: Fehler mit aria-describedby zugeordnet -->
<input
type="password"
aria-label="Passwort (mindestens 8 Zeichen)"
aria-invalid="true"
aria-describedby="pwd-error"
autocomplete="new-password">
<div id="pwd-error" role="alert">
Passwort muss mindestens 8 Zeichen enthalten
</div>Verwendete ARIA-Attribute:
aria-label: Bietet ein barrierefreies Labelaria-describedby: Verknüpft eine detaillierte Beschreibungaria-required: Zeigt ein erforderliches Feld anaria-invalid: Signalisiert ein ungültiges Feldaria-labelledby: Verweist auf ein vorhandenes Labelrole="alert": Sagt Fehler sofort anaria-hidden: Versteckt dekorative Elementearia-live: Sagt dynamische Änderungen an
Erklärung: ARIA-Attribute reichern Formulare an, indem sie Labels, Beschreibungen und Zustände für Hilfstechnologien bereitstellen.
Barrierefreies Akkordeon
Schlechtes Beispiel
Ohne ARIA-Attribute
<!-- Schlecht: Keine ARIA-Attribute, keine Tastaturnavigation -->
<div class="accordion-header" @click="toggle">
<span>Title</span>
<span>+</span>
</div>
<div v-if="open">
Content
</div>Gutes Beispiel
Mit korrektem ARIA
<!-- Gut: Vollständiges ARIA mit Tastaturnavigation -->
<button
id="accordion-button-1"
aria-expanded="false"
aria-controls="panel-1"
@click="toggle"
@keydown.enter="toggle"
>
Title
</button>
<div
id="panel-1"
role="region"
aria-labelledby="accordion-button-1"
:hidden="!open"
>
Content
</div>Erklärung: Ein Akkordeon muss geeignete ARIA-Attribute verwenden, Tastaturnavigation unterstützen und Zustandsänderungen ansagen.
Tabindex und Tastaturnavigation
Das tabindex-Attribut steuert, ob ein Element Tastaturfokus erhalten kann und in welcher Reihenfolge.
✅ tabindex="0"
Element ist in der natürlichen DOM-Reihenfolge fokussierbar
tabindex="0"<!-- Gut: Interaktives Element fokussierbar -->
<div role="button" aria-label="Custom action" tabindex="0">
Custom button
</div>⚠️ tabindex="-1"
Fokussierbar durch JavaScript, aber nicht durch Tab
tabindex="-1"<!-- Gut: Für programmatischen Fokus -->
<div role="alert" aria-live="assertive" tabindex="-1">
Error message
</div>❌ tabindex > 0
Ändert die Navigationsreihenfolge (vermeiden!)
tabindex="5"<!-- Schlecht: Bricht natürliche Tab-Reihenfolge -->
<button tabindex="3">Third</button>
<button tabindex="1">First</button>
<button tabindex="2">Second</button>📋 Tabindex Best Practices
- Verwenden Sie
tabindex="0", um benutzerdefinierte interaktive Elemente fokussierbar zu machen - Verwenden Sie
tabindex="-1"für programmatischen Fokus (Modals, Warnungen) - Verwenden Sie NIEMALS positive Werte - respektieren Sie die DOM-Reihenfolge
- Native interaktive Elemente (
<button>,<a>,<input>) benötigen keinen tabindex
🎯 Interaktive Beispiele
Testen Sie die Tastaturnavigation (Tab/Shift+Tab) mit diesen Elementen:
❌ Nicht fokussierbare Elemente
Absatz
💡 Test-Tipps
- Verwenden Sie Tab, um vorwärts zu navigieren
- Verwenden Sie Shift + Tab, um rückwärts zu navigieren
- Verwenden Sie Leertaste oder Enter, um Elemente zu aktivieren
- Beobachten Sie den Fokusindikator (blaue Umrandung)
- Beachten Sie, welche Elemente Fokus erhalten können oder nicht
Barrierefreies Dropdown-Menü
Schlechtes Beispiel
Menü ohne ARIA
<!-- Schlecht: Keine Menürolle, keine Fokusfalle -->
<div @click="open = !open">
Actions ▼
</div>
<div v-if="open">
<div @click="action">Edit</div>
<div @click="action">Delete</div>
</div>Gutes Beispiel
Menü mit ARIA
<!-- Gut: ARIA-Attribute und Fokusverwaltung -->
<button
aria-haspopup="true"
aria-expanded="false"
aria-controls="menu"
@keydown.escape="close"
>
Actions
</button>
<div
id="menu"
role="menu"
v-if="open"
>
<button role="menuitem">Edit</button>
<button role="menuitem">Delete</button>
</div>Erklärung: Ein Dropdown-Menü muss Tastaturnavigation unterstützen, mit Escape schließen und den Fokus angemessen beibehalten.
Barrierefreie Bildgalerie
Schlechtes Beispiel
Barrierefreie Bildgalerie
<!-- ❌ Schlecht: Galerie nicht mit Tastatur zugänglich -->
<div class="thumbnails">
<img v-for="image in images"
:src="image.thumb"
@click="selectImage(index)"
:class="{ active: selected === index }" />
</div>
<div class="main-image">
<img :src="images[selected].full" />
</div>Gutes Beispiel
Barrierefreie Bildgalerie
Frontansicht des 16-Zoll MacBook Pro mit geschlossenem Bildschirm, zeigt das schlanke Aluminiumdesign.
<!-- ✅ Gut: Barrierefreie Galerie mit Tastaturnavigation -->
<div role="tablist" aria-label="Produktbilder">
<button v-for="(image, index) in images"
:id="`tab-${index}`"
role="tab"
:aria-selected="selected === index"
:aria-controls="`panel-${index}`"
:tabindex="selected === index ? 0 : -1"
@click="selectImage(index)"
@keydown="handleKeydown($event, index)">
<img :src="image.thumb" :alt="`${image.alt} - Miniature`" />
</button>
</div>
<div :id="`panel-${selected}`"
role="tabpanel"
:aria-labelledby="`tab-${selected}`">
<img :src="images[selected].full" :alt="images[selected].alt" />
<p>{{ images[selected].description }}</p>
</div>
<!-- Bonnes pratiques :
- Pattern tablist/tab/tabpanel ARIA
- Navigation avec flèches, Home, End
- Focus management avec tabindex
- Descriptions détaillées pour chaque image -->Erklärung: Eine Bildgalerie muss Tastaturnavigation ermöglichen und kontextuelle Beschreibungen für jedes Bild bereitstellen. Das ARIA tablist/tab/tabpanel-Muster ist perfekt für diesen Anwendungsfall.
Barrierefreie sortierbare Tabelle
Schlechtes Beispiel
| Name ↑ | Rolle | Status | |
|---|---|---|---|
| Alice Martin | alice@example.com | Admin | Aktiv |
| Bob Dupont | bob@example.com | Benutzer | Inaktiv |
| Charlie Leroy | charlie@example.com | Moderator | Aktiv |
| Diana Moreau | diana@example.com | Benutzer | Gesperrt |
Gutes Beispiel
| Alice Martin | alice@example.com | Admin | Aktiv |
|---|---|---|---|
| Bob Dupont | bob@example.com | Benutzer | Inaktiv |
| Charlie Leroy | charlie@example.com | Moderator | Aktiv |
| Diana Moreau | diana@example.com | Benutzer | Gesperrt |
Erklärung: Eine sortierbare Tabelle muss den aktuellen Sortierstatus anzeigen, Tastaturnavigation ermöglichen und Änderungen an Bildschirmleseprogramme ansagen.
Dynamische aria-live Regionen
Schlechtes Beispiel
Ohne aria-live
Änderungen werden nicht angesagt
<!-- Mauvais : pas d'attribut aria-live -->
<div class="status-banner">
<p></p>
</div>Zähler: 0
Probleme:
- Änderungen werden nicht angesagt
- Bildschirmleser-Benutzer wissen nicht, dass sich der Inhalt geändert hat
- Keine Angabe der Wichtigkeit der Nachricht
Gutes Beispiel
Mit geeignetem aria-live
Änderungen werden entsprechend ihrer Priorität angesagt
<!-- Bon : avec aria-live="polite" pour informations -->
<div
class="status-banner"
aria-live="polite"
aria-atomic="true"
role="status"
>
<p>Information : Données mises à jour</p>
</div>
<!-- Bon : avec aria-live="assertive" pour alertes -->
<div
class="alert-banner"
aria-live="assertive"
aria-atomic="true"
role="alert"
>
<p>Attention : Action requise immédiatement</p>
</div>Polite Zone (Informationen)
Assertive Zone (Warnungen)
Vorteile:
- Wichtige Nachrichten unterbrechen mit aria-live="assertive"
- Informationsnachrichten warten mit aria-live="polite"
- aria-atomic="true" sagt gesamten Regionsinhalt an
- Geeignete Rollen (status, alert) bieten mehr Kontext
Erklärung: Aria-live Regionen ermöglichen es, Inhaltsänderungen an Bildschirmleseprogramme anzusagen. 'polite' wartet auf das Ende der aktuellen Ansage, 'assertive' unterbricht sofort.
Barrierefreie Icon-Schaltflächen
Schlechtes Beispiel
Gutes Beispiel
Erklärung: Schaltflächen, die nur Icons enthalten, müssen ein aria-label oder visuell versteckten Text haben, um von Bildschirmleseprogrammen verstanden zu werden.
Combobox / Suche mit Vorschlägen
Schlechtes Beispiel
Ohne ARIA oder Tastaturnavigation
Gutes Beispiel
Mit ARIA und Tastaturnavigation
Erklärung: Eine Suche mit Vorschlägen (Combobox) muss mit der Tastatur navigierbar sein, Ergebnisse ansagen und Auswahl ermöglichen.
Toast-Benachrichtigungen (Live Regions)
Schlechtes Beispiel
Ohne aria-live
❌ Benachrichtigungen werden nicht an Bildschirmleseprogramme angesagt
<!-- Schlecht: nicht an Bildschirmleseprogramme angesagt -->
<div v-if="showToast" class="toast">
Votre demande a été enregistrée
</div>Gutes Beispiel
Mit geeignetem aria-live
✅ Benachrichtigungen werden ordnungsgemäß angesagt
<!-- Gut: Info-Benachrichtigung (polite) -->
<div
v-if="showToast"
role="status"
aria-live="polite"
aria-atomic="true"
class="toast"
>
<p>Votre demande a été enregistrée</p>
<button @click="dismiss" aria-label="Fermer notification">✕</button>
</div>
<!-- Gut: Fehlerwarnung (assertive) -->
<div
v-if="showError"
role="alert"
aria-live="assertive"
aria-atomic="true"
class="toast error"
>
<p>Erreur : action impossible à exécuter</p>
<button @click="dismiss" aria-label="Fermer alerte">✕</button>
</div>Unterschiede:
role="status"+aria-live="polite": Für informative Benachrichtigungen, unterbricht nicht das aktuelle Lesenrole="alert"+aria-live="assertive": Für kritische Fehler, unterbricht sofortaria-atomic="true": Sagt gesamten Benachrichtigungsinhalt an
Erklärung: Dynamische Benachrichtigungen müssen an Bildschirmleseprogramme angesagt werden, ohne den Fokus zu stehlen. Verwenden Sie role='status' für Infos und role='alert' für Fehler.