uHTML.de Nachschlagewerke für die tägliche HTML-Arbeit

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.

Die input-Typen und wofür sie gedacht sind
TypWofü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-level2 für den Ort, new-password beim 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. numeric für reine Ziffern, decimal mit Komma, tel mit Telefontasten, email mit @-Taste.
pattern
Ein regulärer Ausdruck, den die Eingabe erfüllen muss. Immer mit title kombinieren, 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. maxlength schneidet 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. Ein disabled-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

  • name vergessen. 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> ohne type. In einem Formular gilt automatisch submit – ein Knopf, der nur etwas aufklappen soll, schickt sonst das Formular ab.
  • Verschachtelte Formulare. Nicht erlaubt; der Parser wirft das innere weg.