Komponenten · Formulare
Fehlermeldungen barrierefrei gestalten
Eine barrierefreie Fehlermeldung ist sichtbarer Text, der über aria-describedby fest am Feld hängt und beim Absenden auch angekündigt wird. Ein rot umrandetes Feld ohne Text ist für einen Screenreader keine Meldung, sondern gar nichts – und für Menschen mit Rot-Grün-Sehschwäche kaum mehr.
Formulare sind die Stelle, an der sich entscheidet, ob eine Seite benutzbar ist oder zur Sackgasse wird. Der WebAIM-Million-Report vom Februar 2026 zählt fehlende Formularbeschriftungen auf 51 % aller untersuchten Startseiten – und wo schon das Label fehlt, ist die Fehlermeldung selten sauber angebunden. Dabei braucht es dafür kein Framework, sondern natives HTML und eine Handvoll ARIA-Attribute an der richtigen Stelle.
Das Wichtigste in Kürze
- Drei Bedingungen müssen zusammenkommen: Der Fehler ist als Text wahrnehmbar, per
aria-describedbydem Feld zugeordnet und beim Absenden hörbar. -
aria-invalid="true"erst nach der Prüfung setzen. Im Ausgangszustand gesetzt, hört man beim ersten Durchtabben nur „ungültig, ungültig, ungültig“. - Farbe darf betonen, nicht tragen – das verlangt WCAG 1.4.1 „Benutzung von Farbe“ (Stufe A).
- Bei mehr als drei Feldern lohnt eine Fehlerübersicht, die den Fokus bekommt und per Sprungmarke ins jeweilige Feld verlinkt.
- Der Fehlertext nennt Ursache und Ausweg: „Bitte gib eine E-Mail-Adresse mit @ an“ statt „Ungültige Eingabe“.
- Native Fehlerblasen sind kein Ersatz. Sie verschwinden von selbst, lassen sich nicht gestalten und sprechen die Sprache des Browsers, nicht die der Seite.
- Nach einem Seitenneuladen schweigt jede Live-Region. Serverseitig gerenderte Fehler brauchen Fokus-Management statt Ansage.
Was die WCAG verlangt
Fehlermeldungen sind eines der wenigen Themen, an dem gleich fünf Erfolgskriterien hängen. Das ist kein Zufall – hier fallen Wahrnehmung, Bedienung und Verständnis zusammen:
| Kriterium | Stufe | Was es fordert |
|---|---|---|
| 3.3.1 Fehlererkennung | A | Das fehlerhafte Feld wird benannt und der Fehler in Textform beschrieben |
| 3.3.3 Fehlervorschlag | AA | Wenn eine Korrektur bekannt ist, wird sie vorgeschlagen |
| 1.4.1 Benutzung von Farbe | A | Farbe ist nie der einzige Träger der Information |
| 4.1.3 Statusmeldungen | AA | Die Meldung ist ermittelbar, ohne dass sie den Fokus bekommt |
| 3.3.4 Fehlervermeidung | AA | Rechtlich oder finanziell bindende Eingaben lassen sich prüfen und korrigieren |
Praktisch heißt das: Es reicht nicht, dass ein Fehler sichtbar ist. Er muss benannt, verknüpft und angekündigt sein.
Drei Anforderungen an eine Fehlermeldung
| Anforderung | Heißt konkret |
|---|---|
| Wahrnehmbar | Text, nicht nur Farbe; klar formuliert; ggf. mit Symbol |
| Zugeordnet | per aria-describedby fest mit dem Feld verknüpft |
| Angekündigt | beim Absenden hörbar – über Fokus oder eine Live-Region |
Das ist mein Prüfraster, wann immer ich Validierung umsetze. Gehen wir es der Reihe nach durch.
Wahrnehmbar: Text statt Farbe
Ein rot umrandetes Feld sagt jemandem mit Rot-Grün-Sehschwäche oder am Screenreader genau nichts. Eine Fehlermeldung braucht also Text – und der sollte konkret sein:
| Statt | Besser |
|---|---|
| „Ungültige Eingabe.“ | „Bitte gib eine E-Mail-Adresse mit @ an, z. B. name@example.com.“ |
| „Fehler im Feld PLZ.“ | „Die Postleitzahl besteht aus 5 Ziffern.“ |
| „Passwort zu schwach.“ | „Das Passwort braucht mindestens 12 Zeichen. Aktuell sind es 7.“ |
| „Pflichtfeld.“ | „Bitte gib deinen Vornamen an.“ |
Der Unterschied ist nicht Stil, sondern 3.3.3 Fehlervorschlag: Wenn die richtige Eingabe bekannt ist, muss sie genannt werden. Farbe und Symbol dürfen zusätzlich betonen – tragen muss die Aussage der Text. Dass der rote Ton dabei genug Kontrast hat, wird gern übersehen; das Thema vertieft Farbkontraste richtig einstellen.
Zugeordnet: aria-describedby und aria-invalid
Damit ein Screenreader den Fehler beim Fokussieren des Feldes mitliest, muss er programmatisch verbunden sein. Das übernimmt aria-describedby, und aria-invalid markiert den Zustand:
<label for="email">E-Mail-Adresse</label>
<input
type="email"
id="email"
name="email"
aria-invalid="true"
aria-describedby="email-hinweis email-fehler"
/>
<p id="email-hinweis">Wir nutzen die Adresse nur für die Bestellbestätigung.</p>
<p id="email-fehler" class="feldfehler">
Bitte gib eine gültige E-Mail-Adresse an, z. B. name@example.com.
</p>
aria-describedby nimmt mehrere IDs, getrennt durch Leerzeichen – Hinweis und Fehler können also nebeneinander bestehen. Wird der Fehler behoben, entferne ich aria-invalid (oder setze es auf false) und nehme die Fehler-ID wieder aus der Liste. Der Zustand des Feldes bleibt so immer korrekt.
Zwei Fallstricke, die in der Praxis Zeit kosten:
aria-invalid und required beißen sich. Sobald die native Validierung greift, melden manche Browser ein leeres Pflichtfeld von sich aus als ungültig. Zusammen mit einem eigenen aria-invalid="true" entstehen dann Ansagen wie „erforderlich, ungültiger Eintrag, ungültiger Eintrag“. Jan Eric Hellbusch hat die
Unregelmäßigkeiten von aria-invalid
über mehrere Screenreader durchgetestet – wer beides kombiniert, sollte die Ausgabe selbst nachhören.
aria-errormessage ist noch keine Alternative. Das Attribut ist genau für diesen Zweck gedacht, wirkt aber nur zusammen mit aria-invalid="true", und die Unterstützung ist Stand Juli 2026 uneinheitlich: JAWS produziert zusätzlichen Text, andere Screenreader ignorieren es. aria-describedby bleibt der verlässliche Weg.
Angekündigt: Fehlerübersicht oder Live-Region
Beim Absenden eines fehlerhaften Formulars muss klar werden, dass und wo etwas schiefging. Es gibt zwei bewährte Wege, und die Feldzahl entscheidet.
Bei kurzen Formularen genügt oft role="alert" an der Meldung selbst – der Text wird vorgelesen, sobald er erscheint. Voraussetzung ist, dass der Container schon vorher im DOM liegt; wie Live-Regionen genau funktionieren, steht unter Live-Regionen mit aria-live.
Ab etwa drei bis vier Feldern ist die Fehlerübersicht überlegen. Alle Fehler kommen gebündelt an den Anfang des Formulars, der Fokus springt dorthin, und jeder Eintrag verlinkt direkt ins betroffene Feld:
<div class="fehleruebersicht" role="alert" tabindex="-1" id="fehler-oben">
<h2>Bitte korrigiere 2 Eingaben</h2>
<ul>
<li><a href="#email">E-Mail-Adresse: Das @ fehlt</a></li>
<li><a href="#plz">Postleitzahl: Bitte 5 Ziffern eingeben</a></li>
</ul>
</div>
// nach fehlgeschlagener Prüfung
document.getElementById('fehler-oben').focus();
Das tabindex="-1" macht den Container per Skript fokussierbar, ohne ihn in die Tab-Reihenfolge zu hängen. Und die Zahl in der Überschrift hat einen zweiten Nutzen: Sie ändert sich bei jedem Versuch, wodurch die Ansage erneut ausgelöst wird – bei identischem Text bliebe die Region stumm.
Der richtige Zeitpunkt
Wann geprüft wird, entscheidet über die halbe Erfahrung. Eine Prüfung bei jedem Tastendruck – „E-Mail ungültig“, während man noch tippt – ist der sicherste Weg, Menschen zu verunsichern, die ohnehin langsamer eingeben.
Ich mach’s inzwischen andersrum, und das hat sich über viele Projekte gehalten:
- Beim Absenden vollständig prüfen. Das ist der Moment, in dem eine Aussage überhaupt zulässig ist.
- Danach beim Verlassen des Feldes nachprüfen (
blur), aber nur bei Feldern, die schon einmal als fehlerhaft markiert waren. - Fehler sofort entfernen, sobald die Eingabe stimmt – noch während des Tippens. Lob früh, Tadel spät.
Ein Sonderfall sind Felder mit Format-Anforderungen wie Passwörter: Dort gehört die Regel vor die Eingabe, nicht in die Fehlermeldung. Mehr dazu unter Validierung & Pflichtfelder.
Was die native Browser-Validierung kann
Die HTML-Constraint-Validierung (required, type="email", pattern, min) ist eine gute Grundlage: Sie funktioniert ohne JavaScript, ist maschinenlesbar und liefert die Prüfung gleich mit. Ihre Ausgabe hat allerdings vier praktische Grenzen:
- Die Fehlerblase verschwindet von selbst – nach wenigen Sekunden oder beim nächsten Klick. Wer langsam liest, hat sie verpasst.
- Sie zeigt immer nur einen Fehler, nämlich den des ersten ungültigen Feldes.
- Sie lässt sich nicht gestalten, weder in Schriftgröße noch in Farbe.
- Sie spricht die Sprache des Browsers, nicht die der Seite. Eine deutsche Seite in einem englischen Browser meldet „Please fill out this field“.
Deshalb nutze ich die Constraints als Datenbasis und übernehme die Ausgabe selbst: novalidate am <form>, Prüfung über die Constraint-Validation-API, eigene Meldungen im eigenen Markup.
<form novalidate>
<input type="email" id="email" required />
</form>
if (!feld.checkValidity()) {
zeigeFehler(feld, feld.validity.typeMismatch
? 'Bitte gib eine E-Mail-Adresse mit @ an.'
: 'Bitte fülle dieses Feld aus.');
}
Fehler nach dem Neuladen
Kommt die Fehlerseite vom Server, greift keine Live-Region: Was schon im HTML steht, wenn die Seite fertig geladen ist, gilt nicht als Änderung und wird nicht angesagt.
Zwei Dinge helfen, und beide sind schnell umgesetzt. Erstens: den Seitentitel anpassen – „Fehler: Bestellung abschließen“ ist das Erste, was ein Screenreader nach dem Laden vorliest. Zweitens: den Fokus per kleinem Skript in die Fehlerübersicht setzen, sobald das Dokument bereit ist. Ohne diese beiden Griffe landet man nach dem Absenden wieder ganz oben auf der Seite und muss sich das Formular erneut erarbeiten.
So testest du Fehlermeldungen
- Formular leer absenden. Kommt eine Meldung, und landet der Fokus an einer sinnvollen Stelle?
- Nur mit der Tastatur korrigieren. Von der Übersicht per Enter ins Feld, tippen, weiter – ohne Maus muss der ganze Weg funktionieren.
- Mit Screenreader gegenhören. Beim Fokussieren des Feldes muss der Fehlertext mitkommen; der Weg dahin steht bei Mit NVDA testen.
- In Graustufen ansehen. Die Entwicklerwerkzeuge können Farben simulieren. Was dann nicht mehr erkennbar ist, hängt zu sehr an der Farbe.
- Zweimal denselben Fehler auslösen. Wird die Meldung beim zweiten Absenden auch angesagt? Bei unverändertem Text schweigen Live-Regionen.
Häufige Fehler
- Nur Farbe. Roter Rahmen ohne Text – der häufigste und folgenreichste Fehler.
- Meldung nicht verknüpft. Der Hinweis steht sichtbar daneben, ist aber nicht per
aria-describedbygebunden. Screenreader finden ihn nicht. - Stumme Validierung. Sichtbar passiert etwas, akustisch nichts.
-
aria-invalidvon Anfang an. Beim ersten Durchtabben klingt das ganze Formular kaputt. - Vage Texte. „Fehler“ oder „ungültig“ sagen nicht, was zu tun ist.
- Fokus geht verloren. Nach dem Absenden landet der Fokus irgendwo – idealer ist die Fehlerübersicht oder das erste fehlerhafte Feld.
- Meldung ersetzt das Label. Wenn der Fehlertext den Namen des Feldes überschreibt, weiß niemand mehr, worum es ging.
- Übersicht ohne Meldung am Feld. Beim Korrigieren steht man dann ohne Hinweis da.
Häufige Fragen
role="alert" oder aria-live="assertive"?
role="alert" ist die Kurzform: Es entspricht einer assertiven Live-Region und bringt aria-atomic="true" gleich mit. Für Fehler ist das angemessen. Beides gleichzeitig zu setzen, bringt nichts und kann bei einzelnen Screenreadern eine doppelte Ansage auslösen.
Reicht die native Browser-Validierung nicht?
Als Prüflogik ja, als Ausgabe nein. Die Fehlerblasen sind nicht gestaltbar, verschwinden von selbst, zeigen immer nur einen Fehler und sprechen die Sprache des Browsers statt der Seite. Sinnvoll ist die Kombination: die Constraints als Grundlage behalten, die Meldung selbst ausgeben.
Soll der Fehlertext über oder unter dem Feld stehen?
Solange er per aria-describedby verbunden ist, ist beides zulässig. Visuell finde ich direkt unter dem Feld am klarsten, weil Eingabe und Hinweis zusammen im Blick bleiben. Bei starker Vergrößerung hat die Position darüber einen Vorteil: Sie rutscht nicht aus dem sichtbaren Ausschnitt, wenn die Bildschirmtastatur aufklappt.
Wie kennzeichne ich Pflichtfelder?
Nicht allein mit dem Sternchen. Das required-Attribut sagt es der assistiven Technik, ein sichtbarer Hinweis („Pflichtfelder sind mit * markiert“) sagt es allen anderen. Der umgekehrte Weg ist oft besser: Nur die wenigen optionalen Felder markieren, dann braucht es die Legende gar nicht.
Muss ich jeden Fehler doppelt ausgeben – am Feld und in der Übersicht?
Bei längeren Formularen ja, und das ist keine Redundanz, sondern Arbeitsteilung: Die Übersicht beantwortet „Was ist insgesamt offen?“, die Meldung am Feld beantwortet „Was muss ich hier eingeben?“. Wer nur die Übersicht anbietet, lässt Nutzende beim Korrigieren ohne Hinweis zurück.
Fazit
Eine barrierefreie Fehlermeldung ist sichtbarer Text, fest mit dem Feld verknüpft (aria-describedby plus aria-invalid nach der Prüfung) und beim Absenden hörbar – per Fokus auf eine Fehlerübersicht oder über eine Live-Region.
Dazu kommt die Dosierung: beim Absenden prüfen, danach beim Verlassen des Feldes, Fehler sofort wieder wegnehmen, sobald die Eingabe stimmt. Keine dieser Maßnahmen ist aufwendig, aber zusammen entscheiden sie darüber, ob ein Formular alle bis zum Absenden bringt oder unterwegs abhängt. Und wenn du nur eine Sache umsetzt: Schreib in jede Meldung, was zu tun ist – nicht, was falsch war.
Quellen
- Understanding SC 3.3.1: Error Identification (W3C – Anforderung, das fehlerhafte Element zu benennen und den Fehler in Textform zu beschreiben)
- Ungültige Eingabe – Unregelmäßigkeiten des aria-invalid-Attributs (Jan Eric Hellbusch – Screenreader-Tests zu
aria-invalid,requiredundaria-errormessage)