Semantisches HTML · Interaktive & Medien-Elemente
Formular-Semantik & Input-Typen
Formular-Semantik heißt, aus den 22 Input-Typen und den eigenen Elementen <select>, <textarea> und <datalist> den auszuwählen, der die Bedeutung des Feldes trägt – nicht den, der am flexibelsten aussieht. Der passende type bringt Bildschirmtastatur, Formatprüfung ohne JavaScript und funktionierendes Autofill mit; ergänzt um required, pattern, inputmode und autocomplete-Tokens entsteht daraus ein robustes, zugängliches Formular fast ohne eigenen Code.
Formulare sind damit der Ort, an dem semantisches HTML am meisten zurückgibt. Nichts von diesem Verhalten musst du programmieren – du wählst es aus. Diese Seite betrachtet Formulare aus dem Semantik-Blick: welches Element welche Bedeutung trägt und welches Verhalten der Browser dafür geschenkt mitbringt. Die Bedienbarkeit im Detail – Labels, Fehlermeldungen, Validierung – vertieft der Komponenten-Bereich.
Das Wichtigste in Kürze
-
<form>ist die Klammer, aus der Absenden per Enter, native Prüfung vor dem Abschicken und der Kontext „hier wird etwas eingegeben“ überhaupt erst entstehen. - HTML kennt 22 Input-Typen. Der richtige
typeliefert Bildschirmtastatur, Formatprüfung und Autofill – ohne eine Zeile JavaScript. -
inputmodeändert nur die Tastatur, nicht die Bedeutung. Für eine Postleitzahl gehörttype="text"mitinputmode="numeric"hin, nichttype="number". -
autocomplete-Tokens sind Pflicht, nicht Komfort: Sie erfüllen 1.3.5 Eingabezweck bestimmen (Stufe AA) und beschleunigen das Ausfüllen messbar. -
requiredundpatternersetzen keine serverseitige Prüfung. Sie sind eine Vorabprüfung im Browser, kein Schutz. -
fieldsetmitlegendist der native Weg, eine Gruppe von Radiobuttons oder Checkboxen gemeinsam zu beschriften –fieldsetträgt dafür die Rollegroup. -
<output>,<progress>und<meter>sind die vergessenen Elemente für Ergebnisse und Zustände.<output>hat die Rollestatusund ist damit von sich aus eine Live-Region. - Ein
<div>-Nachbau kostet Rolle, Zustand, Tastaturbedienung, Formularabsenden und Autofill gleichzeitig – nachzulesen unter div vs. span. - WCAG-Bezug: 4.1.2 Name, Rolle, Wert (Stufe A) und 3.3.2 Beschriftungen oder Anweisungen (Stufe A) sind mit nativen Elementen weitgehend erledigt.
Das <form>-Element: die semantische Klammer
<form> umschließt zusammengehörige Felder als eine logische Einheit. Das ist mehr als Kosmetik: Erst dadurch entstehen das Absenden per Enter, die native Prüfung vor dem Abschicken und der Kontext „hier wird etwas eingegeben“, den assistive Technologien brauchen. Ein Screenreader kennt eine search-Rolle für Suchformulare und behandelt benannte Formularbereiche als eigene Region. Ein loses Sammelsurium aus <input>-Elementen ohne <form> verschenkt all das.
Beim Absenden schickt der Browser jedes Feld als name=Wert-Paar. Der name ist damit keine Nebensache, sondern der Schlüssel, unter dem der Server den Wert wiederfindet – ohne name wird ein Feld gar nicht erst übertragen.
<form action="/anmelden" method="post">
<label for="mail">E-Mail</label>
<input type="email" id="mail" name="mail" autocomplete="email" required />
<button type="submit">Anmelden</button>
</form>
method: GET oder POST – eine Bedeutungsfrage
Das method-Attribut ist eine semantische Aussage darüber, was das Absenden bewirkt:
method |
Bedeutung | Wann |
|---|---|---|
get (Standard) |
Abfrage ohne Nebenwirkung – die Werte hängen als ?a=1&b=2 an der URL |
Suche, Filter, Sortierung – Ergebnisse, die man teilen und bookmarken kann |
post |
Vorgang mit Wirkung – die Werte reisen im Anfrage-Körper, nicht in der URL | Anmeldung, Bestellung, Upload, alles Anlegen/Ändern/Löschen |
dialog |
schließt einen umgebenden <dialog> und meldet die Eingabe, ohne etwas zu senden |
Formulare innerhalb eines nativen Dialogs |
Die Faustregel folgt direkt aus der HTTP-Semantik: GET fragt ab, POST verändert. Eine Suche gehört per GET in die URL (wiederholbar, teilbar, ohne Seiteneffekt); ein Kauf oder Login gehört per POST in den Körper (nicht wiederholbar, nicht im Verlauf sichtbar). Wählst du falsch, funktioniert das Formular oft trotzdem – aber es „lügt“ über seine Wirkung, und Passwörter landen in der Adresszeile.
enctype, novalidate, target
Ergänzend steuern drei Attribute das Absende-Verhalten:
-
enctype(nur bei POST):application/x-www-form-urlencodedist der Standard. Für Datei-Uploads mit<input type="file">ist zwingendmultipart/form-datanötig – sonst kommt nur der Dateiname, nicht die Datei an. -
novalidateschaltet die native Prüfung für das ganze Formular ab;formnovalidatean einem einzelnen Button tut dasselbe nur für ihn (praktisch für „Entwurf speichern“). -
targetbestimmt, wo die Antwort erscheint (_self,_blank…) – bei modernen Anwendungen selten gebraucht, da JavaScript das Absenden oft übernimmt.
Das form-Attribut: Felder außerhalb des Formulars
Ein Steuerelement muss nicht innerhalb des <form> stehen. Mit dem form-Attribut, das auf die id des Formulars zeigt, gehört ein Feld logisch dazu, obwohl es im DOM woanders liegt:
<form id="suche" action="/suche" method="get"></form>
…
<input type="search" name="q" form="suche" />
<button type="submit" form="suche">Suchen</button>
Das rettet Layouts, in denen sich verschachteltes HTML nicht sauber umsetzen lässt – die Zusammengehörigkeit bleibt für Browser und assistive Technik trotzdem erhalten.
Die Bausteine: welches Element wofür
Bevor es um Input-Typen geht, lohnt der Überblick über die form-assoziierten Elemente. Jedes trägt eine eigene Bedeutung – der Griff zum passenden erspart den Nachbau:
| Element | Bedeutung |
|---|---|
<input> |
Einzeiliges Feld; sein type bestimmt Bedeutung und Verhalten |
<textarea> |
Mehrzeiliger, frei umbrechbarer Text |
<select> / <option> |
Auswahl aus einer festen Liste; <optgroup> gruppiert Optionen |
<button> |
Bedienelement zum Absenden oder für Aktionen |
<label> |
Verbindet Beschriftung und Feld – die Grundlage jeder Bedienbarkeit |
<fieldset> / <legend> |
Fasst zusammengehörige Felder unter einer gemeinsamen Überschrift |
<datalist> |
Vorschlagsliste zu einem Textfeld (Tippen bleibt möglich) |
<output> |
Ergebnis einer Berechnung, für Screenreader automatisch angesagt |
<progress> |
Fortschritt eines Vorgangs (0 … max) |
<meter> |
Skalarer Messwert in bekanntem Bereich (z. B. Füllstand) |
Input-Typen tragen Bedeutung
Der type eines <input> ist gelebte Semantik – er sagt, was erwartet wird, und löst passendes Verhalten aus: die richtige Bildschirmtastatur, eine native Formatprüfung, das passende Autofill. Die 22 Typen lassen sich in Gruppen ordnen. Was der Browser dabei alles fertig mitliefert, zeigt der Blick auf eine Auswahl der Typen:
Text-artige Eingaben
type |
Bedeutung & Effekt |
|---|---|
text |
Beliebiger einzeiliger Text – der Standard, ohne Sonderverhalten |
search |
Suchfeld – oft mit Lösch-Kreuz, „Suchen“-Taste, gespeicherten Eingaben |
email |
E-Mail – Tastatur mit @, native Formatprüfung; multiple erlaubt mehrere |
url |
Webadresse – URL-Tastatur, prüft auf gültiges Schema (https: …) |
tel |
Telefonnummer – Ziffern-Tastatur, aber keine Formatprüfung (Nummern sind zu vielfältig) |
password |
Verdeckte Eingabe – Zeichen werden maskiert |
Zwei Feinheiten sind wichtig: type="email" akzeptiert bewusst auch name@intranet (ohne Punkt), weil interne Adressen gültig sind. Und type="tel" prüft nichts – willst du ein Format erzwingen, kombinierst du es mit pattern (siehe unten).
<label for="mail">E-Mail</label>
<input type="email" id="mail" name="mail" autocomplete="email" />
Am Smartphone erscheint so die passende Tastatur, und der Browser prüft das Format – geschenkt, nur durch die richtige Typwahl.
Randnotiz – robust von Haus aus. Kennt ein Browser einen
typenicht, behandelt er das Feld schlicht alstype="text". Neue oder exotische Typen sind deshalb risikofrei: Schlimmstenfalls bekommt die Nutzerin ein normales Textfeld, das Formular funktioniert trotzdem. Dieses eingebaute Fallback-Prinzip ist Progressive Enhancement in Reinform.
Zahlen: number und range
-
numberliefert ein Feld mit Auf-/Ab-Pfeilen und akzeptiert nur Zahlen. Ideal für echte Mengen mit Ober- und Untergrenze (min,max,step). Vorsicht bei Werten, die zwar aus Ziffern bestehen, aber keine Rechengrößen sind – Postleitzahl, Konto- oder Kreditkartennummer.numberentfernt dort führende Nullen und lädt zum versehentlichen „Hochscrollen“ ein. Für solche Fälle isttype="text"mitinputmode="numeric"die bessere Wahl. -
rangeist ein Schieberegler für ungefähre Werte (Preisgrenze, Lautstärke). Ohnemin/maxgilt der Bereich 0–100. Da der gewählte Wert nicht sichtbar ist, koppelt man ihn typischerweise an ein<output>.
<label for="preis">Maximalpreis</label>
<input type="range" id="preis" name="preis" min="0" max="1000" step="50" value="500" />
<output for="preis">500</output>
Ein zweiter, oft übersehener Fallstrick von type="number" ist das Dezimaltrennzeichen: Viele Länder – Deutschland eingeschlossen – schreiben 19,99 mit Komma, und die Browser gehen unterschiedlich damit um:
| Browser | Akzeptiert das Komma, wenn … |
|---|---|
| Chrome | … die Browsersprache Deutsch ist (die Spracheinstellung der Nutzerin) |
| Firefox |
… das lang-Attribut der Seite bzw. des Feldes Deutsch ist
|
| Safari | Punkt und Komma werden akzeptiert |
Ein deutsches Preisfeld kann also je nach Browser und Systemsprache mal 19,99 annehmen und mal als ungültig ablehnen. Für Geldbeträge ist deshalb oft type="text" inputmode="decimal" plus serverseitige Normalisierung die verlässlichere Wahl – die Zifferntastatur mit Dezimaltrenner gibt es trotzdem.
Datum & Zeit
type |
Erfasst | Nativer Helfer | Übertragener Wert (normiert) |
|---|---|---|---|
date |
Datum (Jahr-Monat-Tag) | Kalender-Widget | 2026-07-26 |
time |
Uhrzeit | Zeit-Auswahl | 14:30 (immer 24-Stunden-Format) |
datetime-local |
Datum und Uhrzeit | Kalender + Zeit | 2026-07-26T14:30 – ohne Zeitzone |
month |
Monat und Jahr | Monats-Auswahl | 2026-07 |
week |
Kalenderwoche und Jahr | Wochen-Auswahl | 2026-W30 |
Der große Gewinn: Der übertragene Wert ist immer normiert, egal wie die Nutzerin ihn in ihrer Landessprache eingibt – angezeigt wird 26.07.2026, übertragen 2026-07-26. min, max und step grenzen den erlaubten Bereich ein. Zwei Feinheiten: Bei week beginnen Wochen montags, und Woche 1 ist die Woche mit dem ersten Donnerstag des Jahres (ISO 8601). Und datetime-local überträgt keine Zeitzone – bei Terminen über Zeitzonen hinweg muss der Server wissen, wie er den Wert interpretiert. Wo ein eigener, aufwendiger Datepicker nötig ist, lohnt der Blick auf die barrierefreie Datums- & Zeitauswahl – oft reicht aber das native Feld.
Auswahl, Farbe, Datei
-
checkbox– einzelne Ja/Nein-Entscheidung oder Mehrfachauswahl. Mehrere Checkboxen mit gleichemnamebilden eine Gruppe. -
radio– Auswahl genau einer Option. Alle Radios mit demselbennamegehören zusammen; nur eines lässt sich wählen. -
color– öffnet den nativen Farbwähler und liefert immer einen sechsstelligen, kleingeschriebenen Hex-Wert (#ff0000). -
file– öffnet den Datei-Dialog;acceptschränkt die Typen ein (image/*),multipleerlaubt mehrere Dateien. Brauchtenctype="multipart/form-data". -
hidden– überträgt einen Wert, den die Nutzerin nicht sieht (z. B. eine Datensatz-ID).
Buttons: mit Bedeutung absenden
Ein Button ist nicht gleich ein Button – sein type bestimmt, was er tut:
type |
Aufgabe |
|---|---|
submit |
Formular absenden (Standard innerhalb eines <form>) |
button |
Reine JavaScript-Aktion, sendet nicht ab |
reset |
Setzt alle Felder zurück – aus UX-Sicht meist zu vermeiden (versehentliches Löschen) |
Bevorzuge das eigenständige <button>Text</button>: Es kann Text, Icons und Markup umschließen, die ein Screenreader vorliest. Die Input-Varianten (<input type="submit">) brauchen ihren Text im value, und ein <input type="image"> zwingend ein alt. Wofür ein <button> und wofür ein <a> das richtige Element ist, trennt Buttons vs. Links.
Randnotiz – ein falscher
typesendet unerwartet ab. Ein<button>ohnetypeinnerhalb eines Formulars gilt alssubmit. Der „Passwort anzeigen“-Button, der plötzlich das halb ausgefüllte Formular abschickt, ist fast immer ein vergessenestype="button".
Die richtige Tastatur: inputmode und enterkeyhint
Manchmal willst du eine bestimmte Bildschirmtastatur, ohne den ganzen Typ zu wechseln. Dafür gibt es inputmode – ein reiner Tastatur-Hinweis, ohne eigene Prüfung:
inputmode |
Tastatur |
|---|---|
text |
Standardtastatur (Voreinstellung) |
numeric |
nur Ziffern 0–9 (z. B. PIN, Kontonummer) |
decimal |
Ziffern mit Dezimaltrenner |
tel |
Telefon-Tastenfeld |
email |
mit @-Taste |
url |
mit /-Taste |
search |
Return-Taste als „Suchen“ |
none |
keine – für eigene Eingabeoberflächen |
Der Unterschied zum type: type prüft und trägt Bedeutung, inputmode beeinflusst nur die Tastatur. Wo ein passender Typ existiert (email, tel, url, number), nimm ihn. inputmode glänzt bei Sonderfällen – etwa einer Kontonummer, die man als type="text" inputmode="numeric" erfasst, um die Zifferntastatur zu bekommen, ohne die Tücken von type="number".
Verwandt ist enterkeyhint: Es beschriftet die Enter-Taste passend zur Aufgabe – enter, done, go, next, previous, search oder send. In einem mehrstufigen Formular sagt next der Nutzerin, dass es weitergeht statt abzusenden.
Eingaben einschränken: die Constraint-Attribute
HTML bringt eine erste Prüfschicht selbst mit – ganz ohne JavaScript. Diese Attribute beschreiben, was ein Feld annimmt:
| Attribut | Wirkung | Passt zu |
|---|---|---|
required |
Pflichtfeld – leer verhindert das Absenden | fast allen Typen |
pattern |
regulärer Ausdruck, den der Wert erfüllen muss | Text-Typen |
min / max |
erlaubter Zahlen- oder Datumsbereich | number, range, Datum/Zeit |
step |
erlaubte Schrittweite | number, range, Datum/Zeit |
minlength / maxlength |
Mindest-/Höchstlänge in Zeichen | Text-Typen |
multiple |
mehrere Werte erlaubt | email, file |
accept |
erlaubte Dateitypen | file |
readonly |
nicht änderbar, wird aber mitgesendet | Text-Typen |
disabled |
inaktiv und wird nicht mitgesendet | alle |
Der Browser prüft diese Vorgaben beim Absenden und zeigt eine native Meldung an – in der Sprache des Browsers, ohne dass du etwas dafür tust:
type="email" mit required genügt, und der Browser erklärt den Fehler in der Sprache der Nutzerin – hier auf Deutsch, samt Hinweis auf das fehlende @-Zeichen.Über die Pseudoklassen :valid, :invalid und – besser für die UX – :user-invalid lässt sich der Zustand gestalten, ohne bei jedem Tastendruck rot aufzuleuchten:
/* Erst nach der Interaktion als fehlerhaft markieren */
input:user-invalid {
border-color: #c0392b;
}
Mit pattern lassen sich auch deutsche Formate abbilden – wichtig ist der begleitende title, den der Browser in die Fehlermeldung übernimmt:
<label for="plz">Postleitzahl</label>
<input
type="text"
id="plz"
name="plz"
inputmode="numeric"
pattern="[0-9]{5}"
title="Fünf Ziffern, z. B. 50667"
autocomplete="postal-code"
/>
Aber Vorsicht mit zu strengen Mustern: Wer ausländische Adressen, Sonderzeichen in Namen oder ungewohnte Telefonformate wegvalidiert, sperrt echte Menschen aus. Im Zweifel lieber großzügig prüfen und serverseitig normalisieren.
Ein wichtiger Merksatz bleibt: Die native Prüfung ist Komfort, keine Sicherheit. Sie fängt Tippfehler früh ab, lässt sich aber umgehen. Eine belastbare, serverseitige Prüfung gehört immer dazu – die zugängliche Umsetzung der sichtbaren Fehlerbehandlung zeigt Validierung & Pflichtfelder.
Eigene Fehlermeldungen: die Constraint Validation API
Die native Prüfung hat eine JavaScript-Seite, die kaum jemand kennt – dabei ist sie der sauberste Weg zu eigenen, deutschen Fehlermeldungen, ohne die Prüflogik neu zu erfinden. Drei Methoden genügen:
| Methode / Eigenschaft | Aufgabe |
|---|---|
checkValidity() |
prüft still und liefert true/false |
reportValidity() |
prüft und zeigt die native Fehlermeldung an |
setCustomValidity('Text') |
ersetzt die Browser-Meldung durch eigenen Text |
validity (ValidityState) |
sagt, warum ein Feld ungültig ist |
Das validity-Objekt schlüsselt den Grund auf: valueMissing (Pflichtfeld leer), typeMismatch (kein gültiges E-Mail-/URL-Format), patternMismatch (pattern verfehlt), rangeOverflow/rangeUnderflow (max/min verletzt) oder tooShort/tooLong. Damit lassen sich präzise, freundliche Meldungen formulieren:
const feld = document.querySelector('#mail');
feld.addEventListener('input', () => {
if (feld.validity.valueMissing) {
feld.setCustomValidity('Bitte gib deine E-Mail-Adresse ein.');
} else if (feld.validity.typeMismatch) {
feld.setCustomValidity('Das sieht noch nicht wie eine E-Mail-Adresse aus – es fehlt z. B. das @-Zeichen.');
} else {
feld.setCustomValidity(''); // wichtig: leerer String gibt das Feld wieder frei
}
});
Der letzte Punkt ist die häufigste Stolperfalle: Ein einmal gesetztes setCustomValidity blockiert das Absenden dauerhaft – erst der leere String löst die Sperre wieder. Wie daraus eine vollständig zugängliche Fehlerbehandlung mit sichtbaren, per aria-describedby verknüpften Meldungen wird, zeigt Validierung & Pflichtfelder.
autocomplete: Bedeutung maschinenlesbar machen
Das autocomplete-Attribut benennt die Bedeutung eines Feldes maschinenlesbar. Damit weiß der Browser, dass hier der Vorname, dort die Straße und daneben das aktuelle Passwort steht – und kann korrekt vorausfüllen. Das nimmt allen Nutzern Tipparbeit ab, hilft besonders Menschen mit motorischen oder kognitiven Einschränkungen und erfüllt zugleich das WCAG-Kriterium 1.3.5 Eingabezweck bestimmen
– die W3C dokumentiert das in
Technik H98 ausdrücklich als ausreichende Technik. Wichtig dabei: Die Tokens gelten nur für Angaben über die nutzende Person selbst – ein Feld „Name des Empfängers“ bekommt kein name-Token.
<input type="text" id="vorname" name="vorname" autocomplete="given-name" />
Die Werte sind ein festes Vokabular, keine Freitexte – der HTML-Standard definiert über 60 Tokens in fester Grammatik. Die wichtigsten Gruppen:
| Bereich | Tokens |
|---|---|
| Name | name, given-name, family-name, honorific-prefix, nickname |
| Kontakt | email, tel, tel-national, tel-country-code, impp |
| Adresse | street-address, address-line1/-line2, postal-code, address-level2 (Ort), country-name |
| Konto | username, current-password, new-password, one-time-code, webauthn |
| Zahlung | cc-name, cc-number, cc-exp (auch cc-exp-month/-year), cc-csc |
| Sonstiges | bday (auch bday-day/-month/-year), organization, url |
Für zusammengesetzte Angaben lassen sich Tokens in fester Reihenfolge kombinieren: ein optionaler Abschnitt (section-*), dann shipping oder billing, dann ein Kontakttyp (home, work, mobile) und zuletzt das eigentliche Detail-Token. So unterscheidet ein Formular Liefer- von Rechnungsadresse:
<input autocomplete="shipping street-address" />
<input autocomplete="billing street-address" />
Drei Sonderfälle sind Gold wert: autocomplete="new-password" sagt dem Passwort-Manager, hier ein neues starkes Passwort vorzuschlagen; autocomplete="one-time-code" erlaubt es dem Smartphone, den per SMS erhaltenen Code direkt anzubieten – ein spürbarer Gewinn für zugängliche Authentifizierung. Und autocomplete="username webauthn" meldet dem Browser, dass hier auch ein Passkey angeboten werden darf – das webauthn-Token muss dabei immer an letzter Stelle stehen.
Damit Autofill überhaupt greift, braucht ein Feld übrigens ein name- oder id-Attribut und sollte in einem <form> mit Submit-Button stehen – noch ein Grund für die saubere semantische Klammer vom Seitenanfang.
Und autocomplete="off"? Nur, wo es wirklich sein muss (Einmal-Codes, Captchas). Es pauschal übers ganze Formular zu legen, sabotiert das Autofill – und Passwortmanager ignorieren es bei Anmeldefeldern ohnehin oft, aus gutem Grund.
Randnotiz – Bedeutung spart Bedienarbeit. Jede dieser Angaben kostet kaum Aufwand, nimmt Nutzern aber Arbeit ab: die richtige Tastatur, ausgefüllte Felder, eine erste Prüfung ohne Server. Semantik im Formular ist damit unmittelbar spürbarer Komfort – und ein gutes Stück Barrierefreiheit gleich mit. Seit dem BFSG sind zugängliche Formulare für Shops und Dienstleistungen übrigens auch gesetzliche Pflicht.
Auswahllisten: select, optgroup und datalist
Für eine feste Auswahl ist <select> das richtige Element – nativ per Tastatur bedienbar, mit Suche-beim-Tippen und einer plattformeigenen Darstellung. Lange Listen gliedert <optgroup> mit einer label-Überschrift:
<label for="land">Land</label>
<select id="land" name="land">
<optgroup label="Europa">
<option value="de">Deutschland</option>
<option value="at">Österreich</option>
</optgroup>
<optgroup label="Amerika">
<option value="us">USA</option>
</optgroup>
</select>
Soll die Nutzerin frei tippen oder aus Vorschlägen wählen können, ist <datalist> das semantische Werkzeug. Es hängt sich per list-Attribut an ein normales Textfeld und schränkt die Eingabe nicht ein:
<label for="stadt">Stadt</label>
<input type="text" id="stadt" name="stadt" list="staedte" />
<datalist id="staedte">
<option value="Berlin"></option>
<option value="Hamburg"></option>
<option value="München"></option>
</datalist>
Reicht die native Vorschlagsliste nicht (etwa für Autocomplete mit Nachladen), führt der Weg zur Combobox – aber erst, wenn <datalist> wirklich nicht genügt.
Zusammengehöriges gruppieren: fieldset und legend
Mehrere Felder, die zu einer Frage gehören – etwa eine Gruppe von Radio-Buttons – bekommen mit <fieldset> eine Klammer und mit <legend> eine gemeinsame Überschrift. Ein Screenreader stellt die legend jeder einzelnen Option voran, sodass „Standard, Optionsfeld“ zu „Versandart, Standard, Optionsfeld“ wird. Das ist reine Semantik – die Beziehung wird sichtbar und programmatisch. Details und Grenzen zeigt fieldset & legend.
Ergebnisse und Zustände: output, progress, meter
Auch die Ausgabe im Formular hat eigene Elemente – oft übersehen:
-
<output>hält das Ergebnis einer Berechnung (Zwischensumme, Reglerwert). Es ist von Haus aus eine Live-Region: Ändert sich sein Inhalt, sagt der Screenreader ihn an. -
<progress>zeigt den Fortschritt eines Vorgangs (valuevon0bismax); ohnevalueist er unbestimmt („läuft noch“). -
<meter>stellt einen Messwert in einem bekannten Bereich dar – Festplatten-Füllstand, Passwortstärke –, nicht aber Fortschritt. Mitlow,highundoptimumfärbt der Browser den Balken sogar sinnvoll ein.
<progress> und <meter> verwechseln viele: Fortschritt bewegt sich auf ein Ziel zu, ein Messwert beschreibt einen Ist-Zustand.
Warum native Elemente – und nicht <div>-Nachbau
Der rote Faden all dessen: Ein <div>, das mit JavaScript zum Eingabefeld umgebaut wird, sieht vielleicht gleich aus – bringt aber nichts von dem mit, was die nativen Elemente geschenkt liefern. Was beim Nachbau verloren geht:
- Tastaturbedienung und Fokus – nativ vorhanden, sonst mühsam nachzurüsten.
- Ansage für Screenreader (Name, Rolle, Wert – siehe 4.1.2).
- Autofill und die maschinenlesbare Bedeutung aus
autocomplete. - Die passende Bildschirmtastatur am Smartphone.
- Die native Prüfung über
required,pattern& Co. - Das Absenden selbst – ein
<div>ist kein Formularfeld und reist nicht mit.
Das ist die erste Regel von ARIA in Reinform: Nutze das native Element, statt seine Semantik von Hand nachzubauen. Wie schnell aus vermeintlich flexiblen <div>-Konstruktionen eine unwartbare „div-soup“ wird, zeigt der eigene Artikel dazu.
Live-Beispiel: ein durchsemantisiertes Formular
Jedes Feld unten trägt den passenden Typ, ein verknüpftes Label und – wo sinnvoll – ein autocomplete-Token. Probier es mit der Tastatur und, wenn möglich, am Smartphone:
Live-Beispiel: semantische Feldtypen
Kein einziges Feld braucht dafür JavaScript: passende Tastatur, Kalender, Zahlenpfeile und Autofill kommen allein aus der richtigen Typwahl.
Häufige Fehler
-
Alles als
type="text", obwohlemail,tel,dateodernumberpassen würden – und damit passende Tastatur, Prüfung und Autofill verschenkt. -
Felder ohne
<form>, wodurch Enter-Absenden, Kontext und native Prüfung fehlen. -
Fehlendes
name-Attribut, sodass ein Feld gar nicht erst übertragen wird. -
type="number"für Konto-, Karten- oder Postleitzahlen, die dadurch führende Nullen verlieren und sich versehentlich verstellen lassen (inputmode="numeric"ist besser). -
type="number"für Geldbeträge, bei denen das deutsche Komma je nach Browser abgelehnt wird (inputmode="decimal"ist verlässlicher). -
<div>mit Klick-Handler als Button statt<button type="submit">. -
<button>ohnetypeim Formular, der ungewollt absendet. -
autocompleteungenutzt oder pauschaloff, sodass Autofill raten muss oder gar nicht greift. -
setCustomValidityohne Rücksetzen, wodurch das Formular dauerhaft blockiert bleibt. - Placeholder als Ersatz fürs Label – der Hinweis verschwindet beim Tippen und ist kein Ersatz für ein echtes Label.
- Native Typen per JavaScript nachbauen, obwohl der native Typ gereicht hätte.
Häufige Fragen
Ersetzt der Input-Typ die Validierung?
Nein, er ergänzt sie. Die native Prüfung ist eine erste, komfortable Stufe – sie lässt sich aber umgehen. Eine vollständige, zugängliche Validierung und eine serverseitige Prüfung gehören zusätzlich dazu.
Warum nicht für alles type="text"?
Weil der spezifische Typ Bedeutung und Verhalten liefert – passende Bildschirmtastatur, Formatprüfung, Autofill, native Auswahlhelfer. text verschenkt das alles und schiebt die Arbeit auf dich und die Nutzerin ab.
Was passiert, wenn ein Browser einen Input-Typ nicht kennt?
Er behandelt das Feld als type="text" – das Formular bleibt voll funktionsfähig, nur der Komfort des speziellen Typs fehlt. Deshalb ist es risikofrei, die spezifischen Typen zu verwenden: Es gibt keinen Absturz, nur ein Fallback.
Wann type="number" und wann inputmode="numeric"?
type="number" passt zu echten Rechengrößen mit Grenzen (Menge, Alter). Für Ziffernfolgen, die keine Zahlen im mathematischen Sinn sind – Konto-, Karten- oder Postleitzahl –, nimmst du besser type="text" mit inputmode="numeric": Zifferntastatur ja, aber ohne verlorene führende Nullen und ohne versehentliches Hoch-/Runterzählen.
Warum akzeptiert type="number" mein Komma nicht?
Weil die Browser das Dezimaltrennzeichen unterschiedlich interpretieren: Chrome richtet sich nach der Browsersprache, Firefox nach dem lang-Attribut der Seite, Safari akzeptiert Punkt und Komma. Für Preisfelder ist type="text" inputmode="decimal" plus serverseitige Normalisierung die robustere Lösung.
Wie bekomme ich deutsche statt englischer Fehlermeldungen?
Die nativen Meldungen erscheinen automatisch in der Browsersprache der Nutzerin. Willst du eigene Texte, nutzt du die Constraint Validation API: setCustomValidity('…') setzt die Meldung, der leere String setCustomValidity('') gibt das Feld wieder frei.
Brauche ich für jedes Feld autocomplete?
Für persönliche Standarddaten (Name, E-Mail, Adresse, Telefon) ja – es hilft spürbar und erfüllt WCAG 1.3.5. Für freie, einmalige Eingaben ohne feste Bedeutung ist es nicht nötig – und für Angaben über andere Personen (z. B. „Name des Empfängers“) ist es sogar falsch.
Was ist der Unterschied zwischen inputmode und type?
type bestimmt Bedeutung und Verhalten (inklusive Prüfung und Datenformat); inputmode beeinflusst nur die angezeigte Bildschirmtastatur. Gibt es einen passenden type, nimm ihn; inputmode ist für Sonderfälle da.
Muss ein Button innerhalb des <form> stehen?
Nein. Mit dem form-Attribut, das auf die id des Formulars zeigt, gehört ein Button oder Feld logisch dazu, obwohl es im DOM außerhalb liegt.
Fazit
Formular-Semantik heißt: <form> als Klammer mit dem richtigen method, für jedes Feld der passende Input-Typ samt seiner Constraint-Attribute, die richtigen Bausteine (button, select, datalist, textarea, label), inputmode für Sonderfälle und autocomplete für Autofill und WCAG 1.3.5. Wo die Browser-Meldungen nicht reichen, übersetzt die Constraint Validation API die native Prüfung in eigene, verständliche Fehlermeldungen. Jede dieser Entscheidungen liefert Bedeutung und fertiges Verhalten – die beste Bedienbarkeit ist die, die du nicht selbst bauen musst. Wie diese semantische Basis zur voll zugänglichen Bedienung wird, zeigen Labels und Validierung.
- MDN – Das <input>-Element und seine Typen
- MDN – Das autocomplete-Attribut und die Autofill-Tokens
- WHATWG HTML Living Standard – Forms
- WHATWG HTML Living Standard – Autofill-Token-Grammatik
- W3C WAI – Technique H98: Using HTML 5.2 autocomplete attributes
- W3C WAI – Forms Tutorial
- WebAIM – Creating Accessible Forms
- web.dev – Learn Forms (Google)
- GOV.UK Design System – Text input