Formulare
Zuletzt geprüft am von Daniel Weihmann

Formulare sind die Stelle, an der eine Website etwas von ihren Besuchern möchte – und entsprechend die Stelle, an der Nachlässigkeit am meisten kostet. Der Browser bringt dabei mehr mit, als viele nutzen: passende Tastaturen auf Telefonen, das Ausfüllen aus dem Adressbuch, eine eingebaute Prüfung und verständliche Fehlermeldungen in der Sprache des Nutzers.
Das Gerüst
<form action="/kontakt/senden" method="post">
<label for="name">Ihr Name</label>
<input type="text" id="name" name="name"
autocomplete="name" required>
<label for="mail">E-Mail-Adresse</label>
<input type="email" id="mail" name="mail"
autocomplete="email" required>
<label for="text">Nachricht</label>
<textarea id="text" name="text" rows="6"></textarea>
<button type="submit">Nachricht senden</button>
</form>
Drei Dinge daran sind nicht verhandelbar. Jedes Feld braucht ein
name, sonst wird sein Wert nicht übertragen – das ist der
häufigste Grund für „das Formular kommt leer an". Jedes Feld braucht
ein <label> mit for auf die
id. Und das Formular braucht eine Absende-Schaltfläche,
auch wenn per Skript abgeschickt wird: Nur so lässt es sich mit der Eingabetaste
bedienen. Warum gerade die Beschriftung so oft fehlt und was daran hängt, steht bei
webaccessibility.de
ausführlich.
method="post" überträgt die Daten im Rumpf der Anfrage,
get hängt sie an die Adresse. Alles, was persönlich ist, gehört
nicht in eine URL – die landet in Verläufen, Server-Logfiles und im Referrer der
nächsten Seite. get ist für Suchformulare richtig, deren Ergebnis
man verlinken können soll.
Die input-Typen
Der richtige Typ ist die günstigste Verbesserung, die ein Formular bekommen kann: Er bestimmt die Tastatur auf dem Telefon, die eingebaute Prüfung und die Bedienhilfen des Betriebssystems.
| Typ | Wofür |
|---|---|
text |
Einzeilige Eingabe ohne besondere Bedeutung. Der Standard, wenn kein Attribut gesetzt ist. |
email |
E-Mail-Adresse. Prüft auf ein @ mit Text davor und dahinter, blendet auf Telefonen die passende Tastatur ein. |
tel |
Telefonnummer. Prüft absichtlich nichts, weil Nummernformate weltweit zu verschieden sind. Zeigt die Zifferntastatur. |
url |
Vollständige Adresse samt Protokoll. Ohne https:// gilt die Eingabe als ungültig. |
password |
Verdeckte Eingabe. Der Schutz ist rein visuell, übertragen wird im Klartext, wenn die Seite nicht über HTTPS läuft. |
search |
Suchfeld. Manche Browser zeigen ein Kreuz zum Leeren und bieten frühere Eingaben an. |
number |
Zahl mit Pfeilen zum Hoch- und Runterzählen. Nicht für Postleitzahlen oder Kartennummern nehmen. |
range |
Schieberegler. Der genaue Wert ist nicht ablesbar, also nur dort einsetzen, wo es auf ihn nicht ankommt. |
date |
Datum mit Kalender des Betriebssystems. |
time |
Uhrzeit. |
datetime-local |
Datum und Uhrzeit ohne Zeitzone. |
month |
Monat und Jahr. |
week |
Kalenderwoche und Jahr. |
checkbox |
Mehrfachauswahl, unabhängig voneinander an- und abwählbar. |
radio |
Einfachauswahl. Alle Optionen einer Gruppe brauchen denselben name-Wert. |
file |
Dateiauswahl. Mit accept lassen sich Typen vorschlagen, mit multiple mehrere Dateien erlauben. |
color |
Farbwähler, liefert einen Hexadezimalwert. |
hidden |
Unsichtbares Feld für technische Werte. Vom Nutzer manipulierbar, also nie für etwas Sicherheitsrelevantes. |
submit |
Absende-Schaltfläche. Meist besser als eigenes button-Element. |
reset |
Setzt das Formular zurück. Praktisch nie sinnvoll, weil versehentlich getroffen. |
button |
Schaltfläche ohne eigene Funktion, nur mit Skript nutzbar. |
image |
Grafische Absende-Schaltfläche. Braucht ein alt-Attribut. |
type="number" ist enger gefasst, als der Name vermuten
lässt. Es ist für Werte gedacht, mit denen man rechnet und die sich
sinnvoll hoch- und runterzählen lassen – Stückzahlen, Alter, Mengen. Für
Postleitzahlen, Telefon-, Kunden- und Kartennummern ist es falsch: Führende
Nullen gehen verloren, ein Scrollen über dem Feld verändert den Wert, und die
Pfeile ergeben keinen Sinn. Dort gehört type="text" mit
inputmode="numeric" hin.
Die wichtigsten Attribute
- required
- Pflichtfeld. Der Browser verweigert das Absenden und meldet das selbst. Kennzeichnen Sie Pflichtfelder zusätzlich sichtbar, sonst erfährt man erst beim Absenden davon.
- autocomplete
-
Sagt dem Browser, was in das Feld gehört, damit er es aus gespeicherten Daten
ausfüllen kann. Die Werte sind standardisiert:
name,email,tel,street-address,postal-code,address-level2für den Ort,new-passwordbeim Anlegen eines Passworts. Für viele Menschen ist das der Unterschied zwischen zehn Sekunden und zwei Minuten Ausfüllzeit. - inputmode
-
Wählt die Bildschirmtastatur, ohne den Typ zu ändern.
numericfür reine Ziffern,decimalmit Komma,telmit Telefontasten,emailmit @-Taste. - pattern
-
Ein regulärer Ausdruck, den die Eingabe erfüllen muss. Immer mit
titlekombinieren, das die Regel in Worten erklärt – sonst steht der Nutzer vor „Bitte passen Sie das Format an" ohne zu wissen, welches. - min, max, step
-
Grenzen für Zahlen, Daten und Schieberegler.
step="0.01"erlaubt Centbeträge,step="any"hebt die Schrittweite auf. - minlength, maxlength
-
Zeichenzahl.
maxlengthschneidet hart ab, was beim Einfügen längerer Texte verwirrt – ein Zähler daneben hilft. - readonly und disabled
-
Beide sperren die Eingabe, aber nur
readonlyüberträgt den Wert mit. Eindisabled-Feld ist zudem nicht fokussierbar und wird von Screenreadern übersprungen. - placeholder
- Ein Beispiel, kein Label. Er verschwindet beim Tippen, hat in vielen Browsern zu wenig Kontrast und wird nicht zuverlässig vorgelesen. Als Ersatz für die Beschriftung ist er ein echter Fehler.
Auswahl und Gruppen
Radiobuttons und Checkboxen gehören in ein <fieldset> mit
<legend>. Die <legend> stellt die Frage,
die Labels sind die Antworten. Ohne sie hört man im Screenreader „Ja" und
„Nein", ohne zu wissen, worauf.
<fieldset>
<legend>Wie sollen wir antworten?</legend>
<input type="radio" id="w-mail" name="weg" value="mail" checked>
<label for="w-mail">Per E-Mail</label>
<input type="radio" id="w-tel" name="weg" value="telefon">
<label for="w-tel">Per Telefon</label>
</fieldset>
Bei Radiobuttons entscheidet der gemeinsame name über die Gruppe,
der value über den übertragenen Wert. Eine Vorauswahl mit
checked ist sinnvoll, solange sie niemanden benachteiligt – bei
Einwilligungen ist sie unzulässig.
Für längere Listen ist <select> gedacht, mit
<optgroup> für Zwischenüberschriften. Wer freie Eingabe mit
Vorschlägen verbinden will, nimmt ein normales Textfeld mit
list und einer <datalist> – anders als beim
<select> bleibt dabei jeder eigene Wert erlaubt.
Was der Browser selbst prüft
required, type, pattern,
min, max und maxlength ergeben zusammen
eine Prüfung, die ohne eine Zeile JavaScript funktioniert und in der
Systemsprache meldet. Im CSS lassen sich die Zustände mit
:invalid, :valid, :required und
:user-invalid ansprechen.
Lohnend ist dabei :user-invalid: Es greift erst, wenn der Nutzer
das Feld verlassen oder abgeschickt hat. :invalid dagegen färbt
ein leeres Pflichtfeld schon rot, bevor überhaupt jemand hineingeklickt hat.
Die Prüfung im Browser ist Bequemlichkeit, keine Sicherheit.
Sie lässt sich mit den Entwicklerwerkzeugen in Sekunden abschalten. Jede
Eingabe muss auf dem Server erneut geprüft werden – ausnahmslos, auch bei
Feldern, die per hidden übertragen werden.
Fehler zurückmelden
Wenn eine Eingabe nicht passt, braucht der Nutzer drei Dinge: Er muss erfahren, dass etwas nicht stimmt, wo es nicht stimmt und was zu tun ist. Ein roter Rahmen liefert davon nur eines und ist für farbfehlsichtige Menschen unter Umständen gar nichts.
<label for="plz">Postleitzahl</label>
<input type="text" id="plz" name="plz"
inputmode="numeric" pattern="[0-9]{5}"
aria-describedby="plz-hinweis" aria-invalid="true">
<p id="plz-hinweis">Bitte fünf Ziffern, zum Beispiel 06366.</p>
aria-describedby verknüpft den Hinweis mit dem Feld, sodass er
beim Fokussieren mit vorgelesen wird. aria-invalid markiert den
Fehlerzustand. Beides ist auch dann richtig, wenn der Hinweis von Anfang an als
Ausfüllhilfe dasteht. Mehr zu diesen Verknüpfungen steht bei der
Barrierefreiheit in HTML.
Häufige Fehler
-
namevergessen. Das Feld ist sichtbar, ausfüllbar – und kommt nicht an. - Beschriftung nur als Platzhalter. Sobald jemand tippt, ist die Frage weg.
-
Alles
type="text". Verschenkt Tastaturen, Prüfung und automatisches Ausfüllen. -
autocomplete="off"aus Gewohnheit. Erschwert das Ausfüllen ohne Not; für Passwortfelder verhindern Browser es ohnehin weitgehend. Was dabei schiefgehen kann, wenn der Browser das Falsche einsetzt, zeigt Autofill als Fehlerquelle bei Formularen. -
Formular nur per Klick absendbar. Ohne
type="submit"funktioniert die Eingabetaste nicht. -
Ein
<button>ohnetype. In einem Formular gilt automatischsubmit– ein Knopf, der nur etwas aufklappen soll, schickt sonst das Formular ab. - Verschachtelte Formulare. Nicht erlaubt; der Parser wirft das innere weg.
