Über diese Website

Dieser Kasten steht auf jeder Seite in der linken Spalte. Was darin steht, änderst du in der Konfiguration unter Plugins — oder du schaltest ihn dort ab.

Über dieses Handbuch

Dieses Handbuch gehört zur Vorlage Example für QuartzControl. Es erklärt die Vorlage und führt zugleich alles vor, was sie kann.

Der Text hier kommt aus einer Markdown-Datei, nicht aus der Konfiguration.

Formularfehler erst nach der Eingabe anzeigen

Formularfehler erst nach der Eingabe anzeigen

Ziel

Ein Pflichtfeld soll nicht schon beim Laden der Seite rot leuchten, sondern erst, wenn jemand es falsch ausgefüllt und verlassen hat. Wird der Fehler korrigiert, soll die Markierung sofort verschwinden. Das alles ohne JavaScript.

Voraussetzungen

  • Die Regeln für gültige Eingaben stehen im HTML: required, type="email", minlength, pattern, min/max usw. Daraus leitet der Browser ab, ob ein Feld gültig ist.
  • :user-invalid und :user-valid sind Baseline widely available seit 2026-05-02.

Getestet mit / Stand

Stand 2026-10-18. Alle Schritte habe ich in Chrome 155 nachgestellt, Firefox und Safari nicht. Screenreader habe ich nicht getestet.

Vorgehen

Warum nicht einfach :invalid?

:invalid prüft nur den aktuellen Wert. Ein leeres Pflichtfeld ist ungültig, also trifft :invalid schon beim Laden der Seite, bevor überhaupt jemand etwas eingegeben hat. Das Formular begrüßt einen dann mit lauter roten Rahmen.1

:user-invalid trifft erst, wenn die Person mit dem Feld etwas gemacht hat. Früher musste man das per JavaScript nachbauen: Ausgangswert merken, Fokus verfolgen, Änderungen prüfen, Klasse setzen.1

1. Felder im HTML beschreiben

<form>
  <div class="feld">
    <label for="mail">E-Mail</label>
    <input id="mail" type="email" required aria-describedby="mail-hinweis">
    <p id="mail-hinweis" class="hinweis">Zum Beispiel name@example.org</p>
    <p class="fehler">Bitte eine gültige E-Mail-Adresse eingeben.</p>
  </div>
  <button>Absenden</button>
</form>

2. Fehler und Erfolg markieren

input:user-invalid {
  border-color: crimson;
}
input:user-valid {
  border-color: seagreen;
}

3. Fehlermeldung einblenden

Mit :has() reagiert das umgebende .feld auf den Zustand des Eingabefelds und blendet den Fehlertext ein:

.fehler { display: none; color: crimson; }
 
.feld:has(input:user-invalid) .fehler {
  display: block;
}

↗ Beispiel in neuem Tab öffnen

4. Das Zusammenspiel verstehen

So verhält sich :user-invalid im Detail, laut MDN und in Chrome 155 genauso beobachtet:23

SituationErgebnis
Seite geladen, Pflichtfeld leerkeine Markierung
Person tippt Ungültiges, ist noch im Feldnoch keine Markierung
Person verlässt das Feld mit ungültigem WertFehler (:user-invalid)
Person kehrt zurück und korrigiertsofort gültig, schon während des Tippens
Feld war gültig, Person ändert es, bleibt im Feldnoch keine Markierung, erst beim Verlassen
Absendeversuchalle ungültigen Felder markiert, auch unberührte

Das ist genau das Verhalten, das man sich wünscht: Beim ersten Ausfüllen wird man nicht unterbrochen, beim Korrigieren gibt es aber sofort Entwarnung.

5. Mit eigener Fehlerbehandlung: novalidate

Ohne weitere Angaben zeigt der Browser beim Absenden eine eigene Fehlerblase und schickt das Formular nicht ab. Wer das selbst übernehmen will, setzt novalidate an das Formular. In Chrome 155 habe ich dabei Folgendes beobachtet:

  • Das Formular wird abgeschickt, das submit-Event feuert also trotz ungültiger Felder.
  • :user-invalid greift trotzdem nach dem Absendeversuch.

Damit kann man die CSS-Markierung behalten und im submit-Handler mit form.checkValidity() selbst entscheiden, ob gesendet wird. Ob Firefox und Safari sich genauso verhalten, habe ich nicht geprüft.

↗ Beispiel in neuem Tab öffnen

Warum funktioniert das?

Der Browser kennt aus den HTML-Attributen die Regeln für jedes Feld (Constraint Validation) und merkt sich zusätzlich, ob die Person schon damit gearbeitet hat. :user-invalid ist die Kombination aus beidem: ungültig und schon bearbeitet. Nach der ersten Markierung prüft der Browser bei jedem Tastendruck neu, deshalb verschwindet der Fehler beim Korrigieren sofort.2

Fallstricke

  • Farbe allein reicht nicht. Ein roter Rahmen ist für Menschen mit Farbsehschwäche schwer zu erkennen. Deshalb gehört ein Text dazu (Schritt 3) oder zumindest ein Symbol. (Eigene Ergänzung, nicht aus den Quellen.)
  • Eingeblendeter Text wird nicht automatisch vorgelesen. Wenn per CSS ein Fehlertext erscheint, bekommen Screenreader das nicht unbedingt mit. Für eine verlässliche Ansage braucht es aria-describedby auf den Fehlertext oder eine Live-Region, und dafür meist doch etwas JavaScript. (Eigene Einordnung, nicht getestet.)
  • :user-valid sparsam einsetzen. Grüne Haken an jedem Feld sind oft eher Lärm als Hilfe. Bei Feldern mit kniffligen Regeln (Passwort, IBAN) sind sie dagegen nützlich. (Eigene Einordnung.)
  • Gilt nur für Felder mit Regeln. Ein Feld ohne required, type oder pattern ist nie ungültig, also trifft auch :user-invalid nie.

Browsersupport

Laut web-features 3.43.0 (abgefragt 2026-10-18): Baseline widely available seit 2026-05-02 (newly available seit 2023-11-02), Chrome/Edge 119, Firefox 88, Safari 16.5.

Siehe auch

Quellen

Eigene Ergänzungen: die Tabelle (aus MDN abgeleitet und in Chrome 155 nachgeprüft), das Verhalten mit novalidate (nur beobachtet, nicht aus den Quellen) und die Fallstricke zu Farbe, Screenreadern und :user-valid.

Footnotes

  1. The user-valid and user-invalid pseudo-classes (web.dev), Abschnitte „The user interaction pseudo-class selectors“ und „Better user experience with less code“, 2023-11-08. ↩ ↩2

  2. user-valid Pseudoklasse (MDN), Einleitung mit Aufzählung der Auslöser, Stand 2026-10-14. ↩ ↩2

  3. user-invalid Pseudoklasse (MDN), Einleitung, Stand 2026-10-14. ↩

Weiterlesen

Diese Seite gehört zu gui-test — der Beispielvorlage für QuartzControl. Ein Überblick über alle Bereiche steht auf der Startseite.

Auf einem schmalen Bildschirm ist die Navigation oben eingeklappt.