Warum Formulare Sorgfalt verdienen
Formulare sind die Orte, an denen Nutzer bezahlen, sich registrieren, suchen und Nachrichten senden. Gleichzeitig ist es dort, wo sich Frustration konzentriert: Ein fehlendes Label, eine verwirrende Fehlermeldung oder ein Input, der die falsche Tastatur öffnet, kann einen Nutzer innerhalb von Sekunden vertreiben.
Die gute Nachricht ist, dass HTML die meisten dieser Probleme bereits löst. Mit korrekten Labels, den richtigen Input-Typen und nativen Constraints erhalten Sie barrierefreie, mobiloptimierte und validierte Formulare, noch bevor Sie eine einzige Zeile JavaScript schreiben.
Formularstruktur
Ein Formular umschließt seine Steuerelemente und legt fest, wohin und wie diese übermittelt werden sollen.
<!-- signup.html -->
<form action="/signup" method="post">
<label for="email">Email address</label>
<input id="email" name="email" type="email" autocomplete="email" required />
<label for="password">Password</label>
<input id="password" name="password" type="password" minlength="8" required />
<button type="submit">Create account</button>
</form>
- action ist die URL, die die Daten empfängt.
- method ist
getoderpost. - name an jedem Steuerelement ist der Schlüssel in den übermittelten Daten.
- type=“submit” löst die Übermittlung aus; ein einfacher Button innerhalb eines Formulars ist standardmäßig auf submit eingestellt, daher sollte für andere Aktionen
type="button"verwendet werden.
Labels
Jedes Steuerelement benötigt ein Label. Ein Label wird von Screenreadern vorgelesen, dient als größere Klickfläche und bleibt sichtbar, nachdem das Feld ausgefüllt wurde.
<!-- label.html -->
<label for="phone">Phone number</label>
<input id="phone" name="phone" type="tel" autocomplete="tel" />
Du kannst das Steuerelement auch innerhalb des Labels umschließen, wodurch sie implizit miteinander verknüpft werden:
<label>
Subscribe to the newsletter
<input type="checkbox" name="subscribe" />
</label>
Placeholders sind keine Labels. Sie verschwinden, sobald ein Nutzer tippt, haben oft einen schlechten Kontrast und werden nicht zuverlässig vorgelesen. Verwende ein echtes Label und, falls hilfreich, einen Hinweis.
Input-Typen
Die Wahl des richtigen type stellt sicher, dass Nutzer auf Mobilgeräten die passende Tastatur erhalten und ermöglicht eine integrierte Validierung.
| Typ | Verwendung für | Vorteil |
|---|---|---|
| E-Mail-Adressen | E-Mail-Tastatur, Formatprüfung | |
| tel | Telefonnummern | Numerischer Tastenblock |
| number | Numerische Werte | Numerische Eingabe, min/max/step |
| url | Webadressen | URL-Tastatur, Formatprüfung |
| date | Daten | Datumsauswahl (Date Picker) |
| password | Geheimnisse | Maskierte Eingabe |
| search | Suchfelder | Such-Tastatur, Lösch-Button |
| file | Uploads | Dateiauswahl und Typ-Filterung |
Verwenden Sie autocomplete zusammen mit Standard-Tokens wie email, given-name, postal-code und new-password, damit Browser und Passwortmanager die Eingabe unterstützen können.
Steuerelemente gruppieren
Gruppieren Sie zusammengehörige Steuerelemente, damit deren Beziehung für alle ersichtlich ist.
<!-- address.html -->
<fieldset>
<legend>Shipping address</legend>
<label for="street">Street</label>
<input id="street" name="street" autocomplete="address-line1" />
<label for="city">City</label>
<input id="city" name="city" autocomplete="address-level2" />
</fieldset>
fieldset und legend gruppieren Radio-Buttons und verwandte Felder, welche von Screenreadern als Set angekündigt werden. Verwenden Sie für Radio-Gruppen immer ein fieldset mit einem legend.
Native Validierung
HTML bietet über Attribute eine sogenannte Constraint Validation (Einschränkungsvalidierung).
<!-- validate.html -->
<input type="email" name="email" required />
<input type="password" name="password" minlength="8" required />
<input type="number" name="age" min="18" max="120" step="1" />
<input type="text" name="handle" pattern="[a-z0-9_]{3,15}" />
<input type="url" name="website" />
Der Browser blockiert das Absenden des Formulars und zeigt eine Meldung an, wenn eine Einschränkung nicht erfüllt ist. Du kannst diese Zustände mit CSS stylen:
/* styles.css */
input:invalid { border-color: #dc2626; }
input:valid { border-color: #16a34a; }
input:focus-visible { outline: 2px solid #2563eb; }
Native Meldungen sind zwar funktional, aber oft knapp und nicht übersetzt. Für wichtige Formulare solltest du eigene, klare Meldungen mithilfe der Constraint Validation API bereitstellen:
// validate.js
const email = document.querySelector("#email");
email.addEventListener("invalid", () => {
email.setCustomValidity("");
if (email.validity.valueMissing) {
email.setCustomValidity("Please enter your email address.");
} else if (email.validity.typeMismatch) {
email.setCustomValidity("That does not look like an email address.");
}
});
email.addEventListener("input", () => email.setCustomValidity(""));
Denk daran, die benutzerdefinierte Meldung bei der Eingabe wieder zu löschen, da das Feld sonst als ungültig markiert bleibt.
Barrierefreie Fehlermeldungen
Validierungen sind nur dann hilfreich, wenn die Nutzer verstehen, was schiefgelaufen ist.
- Zeigen Sie eine klare Textmeldung neben dem Feld an, nicht nur einen roten Rahmen.
- Verknüpfen Sie diese mit dem Steuerelement mithilfe von
aria-describedby. - Markieren Sie das Feld mit
aria-invalid="true". - Setzen Sie beim Absenden den Fokus auf das erste ungültige Feld.
- Fassen Sie Fehler bei langen Formularen oben zusammen.
<!-- error.html -->
<label for="email">Email address</label>
<input id="email" name="email" type="email" required
aria-invalid="true" aria-describedby="email-error" />
<p id="email-error" class="error">Please enter a valid email address.</p>
Verlassen Sie sich niemals allein auf Farben; kombinieren Sie diese immer mit Text und einem Icon.
Immer auf dem Server validieren
Clientseitige Validierung ist ein Feature für die User Experience, kein Sicherheitsmechanismus. Jeder kann die Seite bearbeiten, JavaScript deaktivieren oder Anfragen direkt senden. Der Server muss Typen, Längen, Formate und Berechtigungen validieren und klare Fehlermeldungen zurückgeben, die der Client anzeigen kann. Siehe den Web Security Guide.
Best Practices
- Geben Sie jedem Steuerelement ein sichtbares, zugeordnetes Label.
- Verwenden Sie den korrekten Input-Typ und
autocomplete-Tokens. - Gruppieren Sie zusammengehörige Steuerelemente mit
fieldsetundlegend. - Bevorzugen Sie native Constraints und erweitern Sie diese anschließend mit der Constraint Validation API.
- Zeigen Sie barrierefreie, spezifische Fehlermeldungen in der Nähe des Feldes an.
- Validieren Sie jede Anfrage erneut auf dem Server.
- Halten Sie Formulare kurz und fragen Sie nur das ab, was Sie wirklich benötigen.
Häufige Fehler
- Verwendung von Placeholdern anstelle von Labels.
- Fehlende
name-Attribute, wodurch Felder nicht übermittelt werden. - Übermittlung sensibler Daten via GET.
- Verlass auf clientseitige Validierung für die Sicherheit.
- Kommunikation von Fehlern ausschließlich über Farben.
- Zurücksetzen des gesamten Formulars bei einem Validierungsfehler, wodurch Eingaben verloren gehen.
Wie geht es weiter?
Formulare kombinieren Markup, Barrierefreiheit und Validierung. Vertiefe dein Wissen über das Markup mit Semantic HTML, mache deine Formulare inklusiv mit dem Accessibility guide und verarbeite die Übermittlungen mit JavaScript. Überprüfe anschließend ein Formular in deiner App anhand der oben genannten Checkliste.