Warum das richtige Element wichtiger ist als jedes ARIA-Attribut
Wer interaktive Bedienelemente als generische div oder span umsetzt, verliert automatisch Tastaturbedienung, Fokusreihenfolge und Screenreader-Ankündigungen und muss all das mühsam mit ARIA nachbauen. Native HTML-Elemente wie button, a, ul und h2 liefern diese Eigenschaften kostenlos mit. Dieser Artikel zeigt, wie ihr semantische Fehler in Magento- und Hyvä-Templates erkennt und durch die richtigen Elemente ersetzt.
Inhaltsverzeichnis
- 1. Warum semantisches HTML das Fundament der Barrierefreiheit ist
- 2. Das Prinzip: Kein ARIA ist besser als schlechtes ARIA
- 3. Div-als-Button und Span-als-Link: die häufigsten Anti-Patterns
- 4. Tastaturbedienung: was semantisches HTML automatisch mitliefert
- 5. Formulare: label, fieldset und native Eingabeelemente richtig nutzen
- 6. Überschriftenhierarchie und Landmark-Elemente
- 7. Listen und Tabellen: Struktur statt visueller Näherung
- 8. Wann ARIA wirklich gebraucht wird
- 9. Praktischer Audit: häufige Fehler erkennen und beheben
- 10. Zusammenfassung
- 11. FAQ
1. Warum semantisches HTML das Fundament der Barrierefreiheit ist
Semantisches HTML teilt dem Browser und darüber jeder assistiven Technologie mit, welche Bedeutung ein Element hat, ohne dass Entwickler diese Bedeutung erst nachbauen müssen. Jedes native Element wie button, a oder select wird vom Browser automatisch in den sogenannten Accessibility Tree übersetzt: eine Datenstruktur mit Rolle, Name, Zustand und Wert, die Screenreader, Sprachsteuerungen und Braillezeilen direkt auslesen. Diese Übersetzung passiert unsichtbar im Browser-Rendering und kostet den Entwickler keine einzige Zeile Code.
div und span sind dagegen bedeutungslose Container ohne jede Rolle im Accessibility Tree. Wird auf ein div ein Klick-Handler gelegt und es sieht per CSS wie ein Button aus, entsteht ein Element, das für sehende Mausnutzer funktioniert, für Tastaturnutzer und Screenreader-Nutzer aber schlicht nicht existiert. Genau dieser Bruch zwischen visueller Erscheinung und tatsächlicher Semantik ist die häufigste Ursache für WCAG-Verstöße in gewachsenen Magento- und Hyvä-Templates, und er lässt sich fast immer durch den Wechsel zum richtigen nativen Element beheben.
2. Das Prinzip: Kein ARIA ist besser als schlechtes ARIA
Die W3C Accessibility API Mappings formulieren die sogenannte "First Rule of ARIA Use": Wenn ein natives HTML-Element oder -Attribut mit der gewünschten Semantik und dem gewünschten Verhalten bereits existiert, soll es genutzt werden, statt es mit einem generischen Element plus ARIA nachzubauen. Der Grund ist einfach: ARIA-Attribute wie role oder aria-expanded teilen assistiven Technologien nur mit, welche Rolle und welchen Zustand ein Element hat. Sie fügen keinerlei Verhalten hinzu. Ein div mit role="button" ist für den Screenreader ein Button, reagiert aber ohne zusätzlichen JavaScript-Code weder auf Enter noch auf die Leertaste und ist ohne tabindex nicht einmal per Tab erreichbar.
Noch gefährlicher ist fehlerhaftes ARIA: Ein role oder aria-*-Attribut, das nicht zum tatsächlichen Verhalten des Elements passt, belügt die assistive Technologie aktiv und führt zu einer schlechteren Erfahrung, als wenn gar kein ARIA vorhanden wäre. Ein aria-expanded="false", das nach dem Klick nie auf true wechselt, oder ein role="dialog" ohne Fokus-Management sind typische Beispiele, bei denen "kein ARIA" tatsächlich die harmlosere Variante gewesen wäre.
<!-- FALSCH: generisches div mit nachgebautem ARIA-Verhalten -->
<div class="accordion-trigger" role="button" aria-expanded="false" onclick="toggle()">
Versandkosten anzeigen
</div>
<div class="accordion-panel" hidden>...</div>
<!-- Tastatur, Fokusring und Enter/Space-Handling fehlen komplett -->
<!-- RICHTIG: natives button-Element, kein zusätzliches ARIA nötig -->
<button type="button" aria-expanded="false" aria-controls="shipping-panel" x-on:click="toggle()">
Versandkosten anzeigen
</button>
<div id="shipping-panel" hidden>...</div>
<!-- NOCH EINFACHER: details/summary brauchen überhaupt kein ARIA -->
<details>
<summary>Versandkosten anzeigen</summary>
<p>Der Versand innerhalb Deutschlands kostet 4,90 EUR.</p>
</details>
3. Div-als-Button und Span-als-Link: die häufigsten Anti-Patterns
In fast jedem Frontend-Audit taucht dasselbe Muster auf: ein div mit onclick-Handler, das per CSS wie ein Button gestylt ist, aber weder tabindex noch role noch eine Tastatursteuerung besitzt. Für Mausnutzer sieht alles normal aus, für Tastaturnutzer ist die Funktion schlicht nicht erreichbar. Der zweite Klassiker ist der span mit Klick-Handler, der optisch wie ein Link aussieht: kein href, also kein echtes Linkziel, kein Eintrag in der Tab-Reihenfolge, keine Statuszeilen-Vorschau beim Hovern, kein Öffnen in neuem Tab per Mittelklick oder Kontextmenü.
Der entscheidende Unterschied zwischen a und button ist semantisch, nicht kosmetisch: Ein Link navigiert zu einer neuen Ressource oder einem Ankerpunkt, ein Button löst eine Aktion auf der aktuellen Seite aus, etwa das Absenden eines Formulars oder das Öffnen eines Menüs. Ein Link ohne href-Attribut ist im Übrigen kein interaktives Element mehr, sondern reiner Text, denn erst das href macht ihn per Tastatur fokussierbar. Diese Unterscheidung konsequent einzuhalten löst die meisten div-als-Button- und span-als-Link-Probleme sofort, ohne dass ein einziges ARIA-Attribut nötig wird.
<!-- FALSCH: span als Link getarnt -->
<span class="link-style" onclick="location.href='/warenkorb'">Zum Warenkorb</span>
<!-- RICHTIG: echtes a-Element mit href -->
<a href="/warenkorb" class="link-style">Zum Warenkorb</a>
<!-- FALSCH: div als Aktions-Button getarnt -->
<div class="btn-primary" onclick="addToCart(productId)">In den Warenkorb</div>
<!-- RICHTIG: button-Element für eine Aktion ohne Navigation -->
<button type="button" class="btn-primary" x-on:click="addToCart(productId)">
In den Warenkorb
</button>
4. Tastaturbedienung: was semantisches HTML automatisch mitliefert
Ein natives button-Element ist ohne eine einzige Zeile JavaScript per Tab erreichbar, reagiert sowohl auf Enter als auch auf die Leertaste, erhält beim Fokussieren einen sichtbaren Fokusring und meldet dem Screenreader Rolle und Beschriftung automatisch. Ein a-Element mit href reagiert nur auf Enter, nicht auf die Leertaste, weil Links traditionell nicht mit der Leertaste ausgelöst werden. Diese Details wirken kleinteilig, entscheiden aber darüber, ob sich eine Komponente für Tastaturnutzer korrekt anfühlt oder nicht.
Wer stattdessen ein div interaktiv macht, muss all das händisch nachbauen: tabindex="0" für die Fokussierbarkeit, einen keydown-Listener, der sowohl auf Enter als auch auf Space reagiert, ein event.preventDefault() bei Space, damit die Seite nicht nach unten scrollt, und häufig auch noch manuelles Fokus-Styling, weil Entwickler den nativen Fokusring gerne mit outline: none entfernen, ohne einen gleichwertigen Ersatz bereitzustellen. Genau dieses Entfernen des Fokusrings ohne Ersatz ist einer der häufigsten WCAG-Verstöße überhaupt, unabhängig davon, ob ein natives oder ein nachgebautes Element betroffen ist.
/* FALSCH: Fokusring entfernt, kein Ersatz vorhanden */
.custom-widget:focus {
outline: none;
}
/* RICHTIG: Fokusring nur für Tastaturnutzer sichtbar, mit klarem Ersatz */
.custom-widget:focus {
outline: none;
}
.custom-widget:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
border-radius: 4px;
}
/* Native Elemente wie button und a haben bereits sinnvolle Vorgaben,
die man im Zweifel besser gar nicht anfasst */
button,
a {
outline-offset: 2px;
}
5. Formulare: label, fieldset und native Eingabeelemente richtig nutzen
Ein <label for="...">, das über das for-Attribut mit der id eines Eingabefelds verknüpft ist, gibt diesem Feld einen programmatisch ermittelbaren Namen, vergrößert die klickbare Fläche auf das gesamte Label und wird vom Screenreader beim Fokussieren automatisch vorgelesen. Ohne diese Verknüpfung, etwa wenn nur ein visuell danebenstehender span oder div als Beschriftung dient, bleibt das Feld für assistive Technologien namenlos, selbst wenn es für sehende Nutzer eindeutig beschriftet aussieht.
fieldset und legend gruppieren zusammengehörige Formularelemente, etwa eine Gruppe von Radiobuttons für die Versandart, und geben dieser Gruppe eine gemeinsame Überschrift, die der Screenreader bei jedem einzelnen Gruppenmitglied mit ansagt. Custom-Checkboxen aus divs, die per JavaScript den Zustand nachbilden, sparen sich zwar die schwer stylebaren nativen Kontrollkästchen, verlieren dabei aber native Validierung, aria-checked-Synchronisation und die Formular-Übermittlung per name/value, die bei einem echten input[type=checkbox] automatisch funktioniert.
<form>
<div class="mb-4">
<label for="email" class="block font-semibold mb-1">E-Mail-Adresse</label>
<input
type="email"
id="email"
name="email"
required
aria-describedby="email-error"
class="border border-gray-300 rounded px-3 py-2 w-full"
>
<p id="email-error" class="text-red-600 text-sm mt-1" x-show="errors.email">
Bitte eine gültige E-Mail-Adresse eingeben.
</p>
</div>
<fieldset class="border border-gray-300 rounded p-4">
<legend class="font-semibold px-2">Versandart</legend>
<label class="flex items-center gap-2 mb-2">
<input type="radio" name="shipping" value="standard" checked>
Standardversand (kostenlos)
</label>
<label class="flex items-center gap-2">
<input type="radio" name="shipping" value="express">
Expressversand (9,90 EUR)
</label>
</fieldset>
</form>
6. Überschriftenhierarchie und Landmark-Elemente
Screenreader-Nutzer navigieren Seiten selten linear von oben nach unten, sondern springen über eine Liste aller Überschriften direkt zum gewünschten Abschnitt, ähnlich einem Inhaltsverzeichnis. Diese Liste funktioniert nur, wenn h1 bis h6 tatsächlich die inhaltliche Struktur abbilden und nicht übersprungen oder rein wegen ihrer visuellen Schriftgröße gewählt werden. Eine h4, die nur wegen einer kleineren Schriftgröße statt einer h2 mit passenden CSS-Klassen verwendet wird, zerstört diese Navigationshilfe, ohne dass sehende Nutzer den Unterschied überhaupt bemerken.
Ergänzend dazu unterteilen Landmark-Elemente wie header, nav, main, aside und footer die Seite in benannte Regionen, zwischen denen Screenreader-Nutzer per Tastenkürzel springen können, statt sich durch jeden einzelnen Menüpunkt zu tabben. Ein main-Element pro Seite ist Pflicht, mehrere nav-Bereiche sollten über aria-label unterscheidbar gemacht werden, etwa "Hauptnavigation" und "Breadcrumb", damit die Liste der Landmarks für den Nutzer aussagekräftig bleibt und nicht aus mehreren gleichnamigen Einträgen besteht.
7. Listen und Tabellen: Struktur statt visueller Näherung
Eine echte ul mit li-Elementen wird vom Screenreader als Liste mit Positionsangabe angesagt, etwa "Eintrag 3 von 7". Werden stattdessen mehrere div-Elemente mit einem CSS-Aufzählungszeichen visuell wie eine Liste dargestellt, geht diese Information komplett verloren: Der Nutzer erfährt weder, dass es sich um eine Liste handelt, noch wie viele Einträge sie hat. Für Navigationen, Produktmerkmale und Warenkorb-Positionen gilt daher: erst die semantisch korrekte Liste, dann das CSS-Styling.
Bei Datentabellen ist die Verknüpfung von th-Zellen mit dem scope-Attribut entscheidend: scope="col" für Spaltenüberschriften und scope="row" für Zeilenüberschriften sorgen dafür, dass der Screenreader beim Navigieren einer Zelle automatisch die zugehörige Spalten- und Zeilenüberschrift mit ansagt. Ohne diese Zuordnung ist eine größere Tabelle mit Screenreader praktisch nicht mehr lesbar, weil der Bezug zwischen Zellwert und Bedeutung verloren geht. Ein caption-Element beschreibt zusätzlich den Zweck der gesamten Tabelle.
<table>
<caption>Verfügbare Versandoptionen und Lieferzeiten</caption>
<thead>
<tr>
<th scope="col">Versandart</th>
<th scope="col">Lieferzeit</th>
<th scope="col">Preis</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Standard</th>
<td>3 bis 5 Werktage</td>
<td>kostenlos</td>
</tr>
<tr>
<th scope="row">Express</th>
<td>1 Werktag</td>
<td>9,90 EUR</td>
</tr>
</tbody>
</table>
8. Wann ARIA wirklich gebraucht wird
ARIA ist nicht grundsätzlich falsch, sondern für genau die Fälle gedacht, in denen kein natives Element mit passender Semantik existiert. Ein Cookie-Hinweis, der beim Laden per JavaScript eingeblendet wird, ohne dass der Nutzer die Seite neu lädt, braucht aria-live="polite", damit der Screenreader die neue Information automatisch ansagt. Ein selbstgebautes Modal braucht role="dialog", aria-modal="true" und ein Fokus-Trap-Skript, weil HTML kein natives Modal-Element mit diesem Verhalten kennt, das native dialog-Element mit showModal() ausgenommen, das diese Arbeit inzwischen selbst übernimmt.
Komplexe Widgets wie Tabs, Comboboxen oder Baumstrukturen erfordern zwingend ARIA-Rollen wie role="tablist", role="tab" und role="tabpanel", weil der Browser für diese Muster keine eingebaute Semantik mitbringt. Wichtig ist dabei, sich strikt an das ARIA Authoring Practices Guide (APG) des W3C zu halten, denn jede dieser Rollen verlangt ein exaktes Tastatur-Interaktionsmuster, etwa Pfeiltasten zum Wechseln zwischen Tabs und ein sogenanntes Roving-Tabindex-Verfahren, bei dem immer nur ein einziges Element der Gruppe im Tab-Fokus steht und die Pfeiltasten den internen Fokus verschieben.
9. Praktischer Audit: häufige Fehler erkennen und beheben
Automatisierte Tools wie axe DevTools oder Lighthouse decken laut eigener Dokumentation nur etwa 30 bis 40 Prozent aller WCAG-Erfolgskriterien zuverlässig ab, weil semantische Korrektheit häufig Kontextwissen erfordert, das ein Tool nicht automatisch prüfen kann. Ein solides manuelles Audit beginnt daher immer mit der Tastatur: die komplette Seite ausschließlich mit Tab, Shift+Tab, Enter und den Pfeiltasten bedienen und prüfen, ob jedes interaktive Element erreichbar ist und einen sichtbaren Fokus zeigt.
Der Chrome DevTools "Accessibility"-Tab zeigt für jedes markierte Element die tatsächliche Rolle, den Namen und den Zustand im Accessibility Tree, unabhängig davon, wie das Element aussieht. Weicht die dort angezeigte Rolle vom visuellen Eindruck ab, etwa "generic" statt "button", ist das ein zuverlässiger Hinweis auf ein div-als-Button-Problem. Ergänzend hilft ein kurzer Screenreader-Stichprobentest mit VoiceOver oder NVDA, bei dem gezielt die Listen der Überschriften und Landmarks durchgegangen werden. Die folgende Übersicht fasst die häufigsten Anti-Patterns aus solchen Audits zusammen.
| Anti-Pattern | Falsch | Richtig | Vorteil des nativen Elements |
|---|---|---|---|
| Klickbarer Button | <div onclick> |
<button> |
Fokus, Tastatur und Rolle automatisch |
| Verlinkter Text | <span onclick> |
<a href> |
Statuszeile, Kontextmenü, Tab-Fokus |
| Abschnittstitel | <div class="heading"> |
<h2> |
Erscheint in der Überschriften-Navigation |
| Aufzählung | <div> mit Bullet-Icon |
<ul><li> |
Listenlänge und Position werden angesagt |
| Formularfeld | <div contenteditable> |
<input> + <label> |
Native Validierung und Label-Verknüpfung |
| Dropdown-Auswahl | Custom <div>-Popup |
<select> |
Tastatur, mobiler Picker, kein ARIA nötig |
Mironsoft
Barrierefreiheits-Audits und WCAG-konforme Umsetzung für Magento- und Hyvä-Shops
Semantisch sauberes, barrierefreies Frontend?
Wir prüfen eure Magento- und Hyvä-Templates auf div-als-Button-Muster, fehlende Formular-Labels und Überschriftenfehler und ersetzen sie durch semantisch korrektes, WCAG-konformes Markup.
Semantik-Audit
Accessibility-Tree-Analyse und manuelle Tastaturprüfung jeder Komponente
Template-Refactoring
div-als-Button, fehlende Labels und Überschriftensprünge in phtml beheben
WCAG-Dokumentation
Nachvollziehbare Prüfberichte für BFSG- und WCAG-2.2-Konformität
10. Zusammenfassung
Semantisches HTML ist keine Stilfrage, sondern die Grundlage jeder barrierefreien Anwendung: Native Elemente wie button, a, ul, h2 und select liefern Fokussierbarkeit, Tastaturbedienung, Fokusring und Screenreader-Semantik automatisch mit, kostenlos und ohne ARIA. Die "First Rule of ARIA Use" bringt es auf den Punkt: Kein ARIA ist besser als schlechtes ARIA, denn ein div mit falscher oder unvollständiger ARIA-Rolle belügt assistive Technologien aktiv. Div-als-Button und span-als-Link sind die häufigsten Anti-Patterns in gewachsenen Templates und lassen sich fast immer durch den Wechsel zum richtigen Element beheben.
ARIA bleibt trotzdem unverzichtbar für Fälle ohne natives Äquivalent: Live-Regionen, Modals und komplexe Widgets wie Tabs oder Comboboxen brauchen explizite Rollen und ein vollständiges, per APG spezifiziertes Tastatur-Interaktionsmuster. Ein solides Audit kombiniert automatisierte Tools, die nur einen Teil der WCAG-Kriterien abdecken, mit manueller Tastaturprüfung und einem Blick in den Accessibility Tree der Browser-DevTools. Wer diese Reihenfolge, erst das richtige native Element, dann gegebenenfalls ARIA, konsequent einhält, baut Interfaces, die für alle Nutzergruppen ohne zusätzlichen Aufwand funktionieren.
Semantisches HTML als Grundlage der Barrierefreiheit: Das Wichtigste auf einen Blick
Kein ARIA ist besser als schlechtes ARIA
Erst prüfen, ob ein natives Element existiert. Falsches oder unvollständiges ARIA ist schlimmer als keins.
div/span sind keine Buttons oder Links
button für Aktionen, a href für Navigation. Beides liefert Tastatur und Fokus kostenlos.
Struktur zuerst, Styling danach
Echte Überschriften, Listen und Tabellen mit scope statt rein visueller Näherung per CSS.
Manuell prüfen, nicht nur automatisiert
Tastaturtest, Accessibility-Tree in den DevTools und Screenreader-Stichprobe ergänzen axe/Lighthouse.