Öffnet in einem neuen Tab
Start › Blog › Barrierefreie Formulare komplett: Label, Fehlermeldungen, Fokus

Barrierefreie Formulare komplett: Label, Fehlermeldungen, Fokus

Veröffentlicht: 7. Oktober 2026
Formulare fallen bei fast jeder Barrierefreiheitsprüfung durch — und kosten direkt Anfragen. Das komplette Markup für Label, Fehlermeldungen und Fokus, gegen WCAG 2.2 AA.
Beitragsbild: Barrierefreie Formulare – Label, Fehlermeldungen, Fokus

Stand: 7. Oktober 2026 · Tutorial-Reihe Barrierefreiheit, Strang Entwicklung · Beitrag 2 von 20

Formulare sind das Element, das bei Barrierefreiheitsprüfungen am häufigsten durchfällt. Und sie sind gleichzeitig das Element, das direkt Geld kostet: Wer das Kontaktformular nicht absenden kann, ruft nicht an. Er geht zur Konkurrenz.

Dieser Beitrag ist die vollständige Umsetzung. Nicht die fünf Tipps, die ich im Kurzbeitrag zu WCAG-konformen Formularen schon zusammengefasst habe, sondern das Markup, das ich in Projekten tatsächlich ausliefere. Mit den Stellen, an denen es regelmäßig schiefgeht.

Zielgruppe: Entwickler und Agenturen. Ich setze HTML, CSS und Grundlagen zu ARIA voraus.

Was ein Formular erfüllen muss

Gegen diese WCAG-2.2-Kriterien prüfe ich jedes Formular. Die Liste ist der Prüfplan für diesen Beitrag:

  • 1.3.1 Info und Beziehungen — Label ist programmatisch mit dem Feld verknüpft, Gruppen sind als Gruppen erkennbar.
  • 1.3.5 Eingabezweck bestimmen — autocomplete auf Feldern für persönliche Daten.
  • 2.4.3 Fokus-Reihenfolge — die Tab-Reihenfolge folgt der Logik des Formulars.
  • 2.4.7 Fokus sichtbar und 2.4.11 Fokus nicht verdeckt — der Fokus ist sichtbar und liegt nicht hinter einem Sticky-Header.
  • 3.3.1 Fehlererkennung — Fehler werden in Textform benannt.
  • 3.3.2 Beschriftungen oder Anweisungen — Pflichtfelder und Formate sind vor der Eingabe erkennbar.
  • 3.3.3 Fehlerempfehlung — die Fehlermeldung sagt, wie der Fehler zu beheben ist.
  • 3.3.7 Redundante Eingabe (neu in 2.2) — bereits eingegebene Daten werden nicht noch einmal abgefragt.
  • 3.3.8 Barrierefreie Authentifizierung (neu in 2.2) — kein kognitiver Test wie ein Bilder-CAPTCHA ohne Alternative.
  • 4.1.2 Name, Rolle, Wert — jedes Bedienelement hat einen zugänglichen Namen und meldet seinen Zustand.

Zum Rechtsstand: In Deutschland (BFSG) und Österreich (BaFG) gilt seit dem 28. Juni 2025 die Pflicht für viele privatwirtschaftliche Angebote. Verbindlich zitiert ist derzeit EN 301 549 in der Fassung 3.2.1, also WCAG 2.1 AA. Die Nachfolgefassung 4.1.1 mit WCAG 2.2 AA hat ETSI am 2. September 2026 veröffentlicht; die Aufnahme ins EU-Amtsblatt ist für Ende 2026 geplant und erst damit wird sie rechtlich maßgeblich. In der Schweiz erfasst die BehiG-Teilrevision erstmals private Anbieter, geplantes Inkrafttreten ist der 1. Januar 2027. Ich baue deshalb heute schon gegen 2.2 — die drei neuen Formularkriterien kosten im Neubau nichts extra, in der Nachbesserung schon.

Label: die eine Verknüpfung, die alles trägt

Jedes Eingabefeld braucht ein sichtbares Label, das programmatisch mit dem Feld verbunden ist. Das ist der Fehler Nummer eins in jedem Audit, und er ist in zwei Zeilen behoben.

<label for="email">E-Mail-Adresse</label>
<input type="email" id="email" name="email" autocomplete="email" required>

Was dabei zählt:

  • for und id müssen exakt übereinstimmen. IDs auf der Seite müssen eindeutig sein — Formulare, die zweimal auf einer Seite eingebunden werden (Header und Footer), brechen hier regelmäßig.
  • Ein Platzhalter ist kein Label. placeholder verschwindet beim Tippen, hat zu wenig Kontrast und wird von Screenreadern uneinheitlich vorgelesen. Nutze ihn nur für ein Beispielformat, nie als einzige Beschriftung.
  • Das Label bleibt sichtbar. Floating Labels sind in Ordnung, wenn das Label nach der Eingabe über dem Feld stehen bleibt und den Kontrast hält.
  • aria-label ersetzt kein sichtbares Label. Es hilft Screenreader-Nutzern, aber nicht Menschen mit Sprachsteuerung, die das sehen müssen, was sie aussprechen sollen. Einzige Ausnahme: ein einzelnes Suchfeld mit sichtbarer Lupe, dort ist aria-label="Suche" vertretbar.

Pflichtfelder markieren

Ein Sternchen allein reicht nicht, weil niemand erklärt, was es bedeutet. Zwei Dinge sind nötig: ein Hinweis vor dem Formular und das Attribut required, das den Zustand an Hilfstechnik meldet.

<p id="pflicht-hinweis">Felder mit * sind Pflichtfelder.</p>

<label for="name">Name <span aria-hidden="true">*</span></label>
<input type="text" id="name" name="name" autocomplete="name" required>

Das aria-hidden am Sternchen verhindert, dass der Screenreader „Name Stern“ liest. Die Pflicht kommt über required an. Wenn fast alle Felder Pflicht sind, dreh es um: markiere die optionalen Felder mit „(optional)“ im Label.

Gruppen: Radiobuttons und Checkboxen

Zusammengehörige Optionen brauchen eine Gruppenbeschriftung. Ohne fieldset hört ein Screenreader-Nutzer „Ja“ und „Nein“, weiß aber nicht, worauf sich die Frage bezieht.

<fieldset>
  <legend>Bevorzugter Kontaktweg</legend>
  <label><input type="radio" name="kontakt" value="mail" checked> E-Mail</label>
  <label><input type="radio" name="kontakt" value="tel"> Telefon</label>
</fieldset>

Das fieldset darfst du stylen. Border weg, Padding weg, legend als normaler Text. Was du nicht darfst: es durch ein div mit einer Überschrift ersetzen. Die Überschrift ist nicht mit den Feldern verknüpft.

Autocomplete: das vergessene Kriterium

WCAG 1.3.5 verlangt, dass Felder für persönliche Daten ihren Zweck maschinenlesbar mitteilen. Das ist das autocomplete-Attribut mit den Werten aus der HTML-Spezifikation. Es hilft Menschen mit motorischen und kognitiven Einschränkungen, weil der Browser ausfüllt.

<input type="text" id="vorname" name="vorname" autocomplete="given-name">
<input type="text" id="nachname" name="nachname" autocomplete="family-name">
<input type="tel" id="tel" name="tel" autocomplete="tel">
<input type="text" id="strasse" name="strasse" autocomplete="street-address">
<input type="text" id="plz" name="plz" autocomplete="postal-code" inputmode="numeric">

Die Werte sind festgelegt. autocomplete="on" erfüllt das Kriterium nicht. autocomplete="off" auf Login-Feldern verstößt zusätzlich gegen 3.3.8, weil es Passwortmanager blockiert. Die vollständige Liste steht in der HTML-Spezifikation.

Das ist gleichzeitig die einfachste Umsetzung von 3.3.7 Redundante Eingabe: Was der Browser ausfüllt, muss niemand zweimal tippen. Wenn dein Formular mehrere Schritte hat, gilt zusätzlich: Rechnungsadresse als Lieferadresse übernehmen muss ein Klick sein, kein zweites Formular.

Fehlermeldungen: benennen, verknüpfen, erklären

Hier scheitern die meisten Formulare, auch die mit sauberen Labels. Drei Dinge müssen zusammenkommen: Der Fehler steht als Text am Feld, der Text ist programmatisch mit dem Feld verknüpft, und er sagt, was zu tun ist.

<label for="email">E-Mail-Adresse <span aria-hidden="true">*</span></label>
<input type="email" id="email" name="email" autocomplete="email" required
       aria-invalid="true" aria-describedby="email-hinweis email-fehler">
<p id="email-hinweis">Beispiel: name@firma.at</p>
<p id="email-fehler" class="fehler">Die E-Mail-Adresse braucht ein @-Zeichen. Bitte prüfe die Eingabe.</p>

Die Bausteine im Einzelnen:

  • aria-invalid="true" setzt du erst nach einer fehlgeschlagenen Prüfung, nie initial. Ein leeres Pflichtfeld beim Laden ist noch kein Fehler.
  • aria-describedby nimmt mehrere IDs, durch Leerzeichen getrennt. Formathinweis und Fehlermeldung werden beide vorgelesen, wenn das Feld den Fokus bekommt.
  • Die Fehlermeldung nennt das Feld und die Lösung. „Ungültige Eingabe“ fällt bei 3.3.3 durch. „Pflichtfeld“ ohne Feldname auch.
  • Farbe allein reicht nicht (1.4.1). Roter Rahmen plus Text ist richtig; roter Rahmen allein nicht. Ein Icon ist optional, der Text nicht.

Nach dem Absenden: Fokus setzen

Wenn das Formular mit Fehlern zurückkommt, muss der Nutzer das erfahren, ohne die Seite abzusuchen. Zwei Muster funktionieren; ich nutze beide je nach Formularlänge.

Kurze Formulare (bis fünf Felder): Fokus auf das erste fehlerhafte Feld setzen. Der Screenreader liest Label, Zustand „ungültig“ und über aria-describedby die Fehlermeldung vor.

const erstesFehlerfeld = form.querySelector('[aria-invalid="true"]');
if (erstesFehlerfeld) {
  erstesFehlerfeld.focus();
}

Lange Formulare: Fehlerzusammenfassung oberhalb des Formulars, die den Fokus bekommt. Jeder Eintrag ist ein Link zum betroffenen Feld.

<div id="fehler-zusammenfassung" tabindex="-1" role="group" aria-labelledby="fehler-titel">
  <h2 id="fehler-titel">Das Formular hat 2 Fehler</h2>
  <ul>
    <li><a href="#email">E-Mail-Adresse: Die Adresse braucht ein @-Zeichen.</a></li>
    <li><a href="#nachricht">Nachricht: Bitte gib eine Nachricht ein.</a></li>
  </ul>
</div>

Das tabindex="-1" macht den Container per Skript fokussierbar, ohne ihn in die Tab-Reihenfolge zu hängen. Der Fokus wird nach dem Rendern mit .focus() gesetzt. Bei serverseitiger Validierung mit Seiten-Reload gehört der Container an den Anfang von main und bekommt den Fokus beim Laden.

Live-Validierung: wann sie hilft, wann sie stört

Validierung bei jedem Tastendruck ist eine Barriere. Wer „m“ tippt, bekommt sofort „ungültige E-Mail-Adresse“ vorgelesen. Validiere bei blur, also beim Verlassen des Feldes, und beim Absenden. Wenn du dynamische Fehlermeldungen einblendest, brauchen sie eine Live-Region, sonst erfährt ein Screenreader-Nutzer nichts davon:

<p id="email-fehler" class="fehler" aria-live="polite"></p>

Die Live-Region muss beim Laden schon im DOM stehen, leer. Erst dann meldet der Screenreader Änderungen am Inhalt. Ein Element, das du mit der Fehlermeldung erst erzeugst, wird oft nicht angesagt.

Native Validierung: ja, aber

Die Browser-eigene Validierung über required und type="email" erfüllt die Kriterien formal — Fehler werden benannt, Fokus wird gesetzt. In der Praxis hat sie Lücken: Die Meldungen sind nicht stylbar, sie verschwinden nach Sekunden, und im Screenreader-Verhalten unterscheiden sich die Browser. Ich nutze novalidate auf dem Formular und baue die Validierung selbst, behalte aber die HTML-Typen und Attribute, damit die Constraint-API (checkValidity()) die Prüflogik liefert.

Fokus: sichtbar, in Reihenfolge, nicht verdeckt

Drei Kriterien, drei typische Fehler.

Sichtbar (2.4.7): outline: none im CSS-Reset ist immer noch verbreitet. Wenn du den Browser-Fokus ersetzt, dann durch etwas, das mindestens 3:1 Kontrast zum Hintergrund hat und auf allen Hintergründen funktioniert. Mein Standard:

:focus-visible {
  outline: 3px solid var(--fokus, #1a5fb4);
  outline-offset: 2px;
}
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline-offset: 0;
  box-shadow: 0 0 0 4px #fff, 0 0 0 7px var(--fokus, #1a5fb4);
}

Die doppelte box-shadow legt einen weißen Ring zwischen Feld und Fokusring. So bleibt der Fokus auch auf dunklen Sektionen sichtbar. Die Details zu den verschärften Anforderungen in 2.2 kommen in einem eigenen Beitrag dieser Reihe.

Reihenfolge (2.4.3): Die Tab-Reihenfolge folgt dem DOM. Wenn dein CSS die Felder visuell umsortiert (order, flex-direction: row-reverse, absolutes Positionieren), springt der Fokus scheinbar wahllos. Sortiere im HTML, nicht im CSS. tabindex mit positiven Werten ist keine Reparatur, sondern die nächste Baustelle. Begriffe rund um Fokus und Tastatur findest du im Glossar.

Nicht verdeckt (2.4.11, neu in 2.2): Sticky-Header, Cookie-Banner und Chat-Widgets legen sich über das fokussierte Feld. Bei Formularen im unteren Seitenbereich passiert das ständig. Die Lösung ist eine Zeile:

html {
  scroll-padding-top: 6rem; /* Höhe des Sticky-Headers plus Luft */
}

Damit scrollt der Browser fokussierte Elemente unter dem Header hervor. Für ein fixes Chat-Widget rechts unten gilt entsprechend scroll-padding-bottom.

Buttons, Selects und Custom-Elemente

Der Absende-Button ist ein <button type="submit"> mit Text. Nicht ein div mit Click-Handler, nicht ein Icon ohne Namen. Wenn der Button nur ein Icon zeigt, braucht er einen Namen über aria-label oder visuell versteckten Text.

Natives <select> ist barrierefrei. Jede Custom-Dropdown-Lösung — und es sind fast alle, die Design-Systeme mitbringen — muss die Tastaturbedienung, die Rollen und die Zustände nachbauen, die der Browser gratis liefert. Das geht, es ist aber ein eigener Beitrag. Meine Regel: Erst natives Select mit CSS auf den sichtbaren Teil (Pfeil, Rahmen, Schrift) anpassen. Custom nur, wenn die Optionen Inhalte brauchen, die ein Select nicht kann.

Datepicker: Ein Textfeld mit klarem Formathinweis („TT.MM.JJJJ“) plus optionalem Kalender-Button ist fast immer die bessere Lösung als ein Pflicht-Kalender. Der Kalender selbst ist ein modaler Dialog mit allen Anforderungen daran.

Spam-Schutz ohne Barriere

WCAG 3.3.8 verlangt, dass Authentifizierung keinen kognitiven Test ohne Alternative voraussetzt. Bilder-CAPTCHAs fallen darunter. Was funktioniert, in dieser Reihenfolge: Honeypot-Feld (verstecktes Feld, das Menschen nicht ausfüllen, Bots schon), Zeitmessung zwischen Laden und Absenden, serverseitige Bewertung. Ein Honeypot muss aus dem Zugänglichkeitsbaum raus, sonst füllt ein Screenreader-Nutzer ihn aus:

<div class="hp" aria-hidden="true">
  <label for="website">Website</label>
  <input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
</div>

Plus .hp { position: absolute; left: -9999px; } im CSS. Nicht display: none — manche Bots erkennen das.

Der Testablauf

Automatische Prüfer finden fehlende Labels und fehlende Namen. Sie finden nicht, ob die Fehlermeldung hilfreich ist oder der Fokus nach dem Absenden am richtigen Ort landet. Deshalb dieser manuelle Ablauf, 15 Minuten pro Formular:

  1. Maus weg. Mit Tab durch das gesamte Formular. Ist jeder Schritt sichtbar? Stimmt die Reihenfolge? Kommst du mit Tab wieder raus?
  2. Leer absenden. Landet der Fokus auf einem Fehler oder einer Zusammenfassung? Sind alle Fehler in Text benannt?
  3. Falsch ausfüllen. Sagt jede Meldung, was zu tun ist?
  4. Screenreader an. NVDA unter Windows, VoiceOver am Mac. Jedes Feld: Wird Label, Typ, Pflicht und Fehler vorgelesen? Wird die Gruppe bei Radiobuttons angesagt?
  5. Zoom 200 %. Bleiben Label und Fehlermeldung beim Feld? Wird nichts abgeschnitten?
  6. Autofill testen. Füllt der Browser Name, E-Mail und Adresse aus?
  7. Sticky-Header. Das letzte Feld fokussieren: Ist es komplett sichtbar?

Für den ersten Überblick über eine fremde Seite reicht mein Barrierefreiheits-Schnellcheck — er meldet fehlende Formular-Labels sofort. Die Schritte 2 bis 7 nimmt dir kein Tool ab.

KI als Werkzeug: wo sie hilft, wo sie schadet

Ich lasse Formular-Markup regelmäßig von einem Sprachmodell gegen die Kriterienliste oben prüfen. Das ist ein brauchbarer erster Durchlauf: fehlende for/id-Paare, fehlendes autocomplete, ein fieldset ohne legend — das findet es zuverlässig. Auch Fehlermeldungen umformulieren lassen („nenne Feld und Lösung in einem Satz“) spart Zeit.

Wo es schadet: bei ARIA. Wenn du ein Sprachmodell bittest, ein Formular „barrierefrei zu machen“, bekommst du fast sicher zu viel davon. role="form" auf einem form-Element, aria-required zusätzlich zu required, aria-label auf Feldern, die schon ein Label haben, role="alert" auf jeder Fehlermeldung — was dann beim Absenden alle gleichzeitig vorgelesen werden. Jedes dieser Attribute ist einzeln harmlos, in Summe ist das Formular für Screenreader-Nutzer lauter und nicht besser. Die Regel „kein ARIA ist besser als falsches ARIA“ bekommt ein eigenes Tutorial in dieser Reihe.

Mein Vorgehen: KI prüft gegen eine Liste, die ich vorgebe. KI schreibt kein Markup, das ich nicht Zeile für Zeile verstehe. Und der Screenreader-Test bleibt bei mir.

Für Agenturen

Wenn du Formulare für Kunden baust, die unter BFSG oder BaFG fallen, ist das hier der Teil, der in der Prüfung zuerst auffällt. Ich setze Formulare und komplette Websites im Hintergrund für Agenturen um — White-Label, gegen WCAG 2.2 AA, mit dokumentiertem Testprotokoll. Für bestehende Seiten gibt es die Prüfung und Umsetzung, die auch die Formulare mit abdeckt.

Häufige Fragen

Reicht ein Platzhalter als Beschriftung, wenn er gut lesbar ist?

Nein. Der Platzhalter verschwindet beim Tippen, und Nutzer mit Sprachsteuerung brauchen ein sichtbares Wort, das sie aussprechen können. WCAG 3.3.2 verlangt eine Beschriftung, die während der Eingabe bleibt.

Muss ich aria-required setzen, wenn required schon da ist?

Nein. required wird von allen aktuellen Browsern und Screenreadern gemeldet. aria-required ist nur für Custom-Elemente ohne natives required gedacht.

Ist die native Browser-Validierung WCAG-konform?

Formal ja: Fehler werden benannt und der Fokus wird gesetzt. In der Praxis sind die Meldungen kurzlebig, nicht stylbar und die Screenreader-Ausgabe ist je nach Browser unterschiedlich. Eigene Validierung mit novalidate plus Constraint-API ist der robustere Weg.

Welche Fehler findet ein automatischer Test nicht?

Unverständliche Fehlermeldungen, falsche Fokus-Reihenfolge, fehlenden Fokus nach dem Absenden, verdeckte Felder unter Sticky-Headern und überflüssiges ARIA. Das sind gleichzeitig die häufigsten Mängel in Prüfberichten.

Gilt WCAG 2.2 schon als gesetzliche Anforderung?

Stand Oktober 2026: In DE und AT ist EN 301 549 v3.2.1 mit WCAG 2.1 AA die zitierte Norm. Die neue Fassung 4.1.1 mit WCAG 2.2 AA ist seit 2. September 2026 veröffentlicht und soll Ende 2026 ins EU-Amtsblatt. In der Schweiz ist die BehiG-Revision für private Anbieter ab 1. Januar 2027 geplant. Gegen 2.2 zu bauen ist heute die sichere Wahl.

Wie schütze ich ein Formular vor Spam ohne CAPTCHA?

Honeypot-Feld außerhalb des Zugänglichkeitsbaums, Zeitmessung zwischen Laden und Absenden, serverseitige Filterung. Das hält in meinen Projekten über 95 Prozent des Spams ab, ohne dass ein Mensch einen Test lösen muss.

Sprich mit mir über dein Projekt.

Du hast ein Formular, das in der Prüfung durchgefallen ist, oder eine Agentur, die Barrierefreiheit im Hintergrund braucht? Erstgespräch buchen — 30 Minuten, kostenlos, mit ehrlicher Einschätzung.

Weitere Beiträge der Reihe: Barrierefreie Webseitentexte schreiben (Strang Redaktion). Alle Beiträge finden sich in der Kategorie Barrierefreiheit.

KI-Transparenz: Die Beitragsbilder in diesem Blog werden mit KI generiert, die Texte entstehen in der Regel mit KI-Unterstützung. Jeder Beitrag wird von mir redaktionell geprüft und inhaltlich verantwortet. So arbeite ich mit KI

Inhalt

Keine Lust auf Selbermachen?

Ich richte deine WordPress-Seite sicher ein — inkl. DSGVO-Check.
Erstgespräch buchen

Geschrieben von Christoph Purin

Webentwickler und zertifizierter Web Accessibility Expert aus Vorarlberg. WordPress seit 2005. Jeder Beitrag basiert auf echten Projekten — alles selbst getestet.
Mehr über mich →So arbeite ich mit KI →

Sprich mit mir über dein Projekt.

30 Minuten, kostenlos, unverbindlich. Du bekommst meine ehrliche Einschätzung — auch wenn sie lautet: „Dafür brauchst du mich nicht.“
Erstgespräch buchen
Antwort innerhalb von 48 Stunden · hallo@purin.at · +43 660 744 13 58