mitmario.dev

Formulare gestalten

CSS Im Browser 4 Min Lesezeit 3 BeispieleLektion 2 von 6

Formularelemente sind der Sonderfall im CSS. Der Browser bringt für sie eigene Bausteine mit, die er selbst zeichnet, und die halten sich an weniger Regeln als der Rest. Was heute geht und was nicht, hat sich in den letzten Jahren stark verschoben.

Der Reset, der immer der erste ist

Ohne Reset und mit Reset
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 24px;
  font-family: Georgia, serif;
  font-size: 17px;
  line-height: 1.6;
}

.etikett {
  margin: 0 0 8px 0;
  font-size: 14px;
  font-family: system-ui, sans-serif;
  color: #52525b;
}

p {
  margin: 0 0 32px 0;
}

/* Die Felder erben die Schrift nicht von allein.
   Und ihr Innenabstand kommt aus einer Zeit, in der
   man Felder mit der Maus traf und nicht mit dem
   Finger. */
.gemacht input,
.gemacht select {
  padding: 10px 12px;
  border: 1px solid #d4d4d8;
  border-radius: 8px;
  font: inherit;
}

input, select und textarea erben keine Schrift. Sie holen sie vom Betriebssystem, so wie der Knopf in Lektion 14.1, und stehen deshalb in einer anderen Familie und einer anderen Größe als alles um sie herum. font: inherit an alle drei ist die erste Zeile jedes Formular-Stylesheets.

Dazu kommen ein eigener Innenabstand, ein eigener Rahmen und ein Radius. Der Default-Innenabstand ist winzig, und ein Feld, das kaum höher ist als sein Text, trifft man auf dem Telefon nicht.

Und eine Zahl, die wichtiger ist, als sie aussieht: mindestens 16 Pixel Schriftgröße in Eingabefeldern. Ist die Schrift kleiner, zoomt iOS beim Antippen automatisch heran, und die Seite steht danach verschoben da. Das ist kein Fehler des Geräts, sondern eine Hilfestellung, die man nur dadurch vermeidet, dass man groß genug schreibt.

Genau diese Zahl kannst du im Auskunftsstreifen ablesen, und sie ist der Grund, warum der Reset keine Geschmacksfrage ist. Zeig auf das obere Feld: font-size: 13.3333px, padding: 1px 2px, und der ganze Kasten misst 179 × 21. Zeig auf das untere: 17px (die Größe der Seite, geerbt), padding: 10px 12px, Maße rund 246 × 49. Die 13,33 sind die Vorgabe des Browsers, und sie liegen unter der Schwelle, ab der iOS in Ruhe lässt.

accent-color

accent-color färbt in einer Zeile
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 24px;
  font-family: system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.5;
}

.gruppe {
  accent-color: #b91c1c;
}

.gruppe p {
  margin: 0 0 12px 0;
}

.hinweis {
  max-width: 60ch;
  margin-top: 24px;
  color: #52525b;
}

Checkbox, Radio, Regler und Fortschrittsbalken zeichnet der Browser selbst, und lange ließ sich daran nichts ändern, ohne das echte Element zu verstecken und ein eigenes daneben zu bauen. accent-color färbt alle vier in einer Deklaration.

Sie vererbt sich, du kannst sie also einmal auf body oder auf das Formular setzen. Der Browser rechnet sich die passende Farbe für Haken und Umrandung selbst dazu, das musst du nicht angeben.

Im Streifen steht sie nicht, dort stehen Layout, Farben und Schrift. Fragen kannst du sie trotzdem, in der Eingabezeile der Console: getComputedStyle(document.querySelector('input[type=checkbox]')).accentColor antwortet im Beispiel rgb(185, 28, 28). Setz die Zeile testweise an eine andere Stelle im Stylesheet und frag noch einmal, dann siehst du die Vererbung als Antwort und nicht als Behauptung.

Der Fokus muss sichtbar sein

Für Formularfelder gilt dasselbe wie für Knöpfe: :focus-visible mit einem deutlichen outline und etwas outline-offset (Lektion 7.3). Wer mit der Tastatur durch ein Formular geht, muss jederzeit sehen, wo er ist.

Der Fokusring ist die Stelle, an der am häufigsten gegen die Bedienbarkeit gestaltet wird. outline: none ohne Ersatz gehört zu den Fehlern, die am häufigsten durchrutschen, weil man beim Bauen mit der Maus arbeitet. Wenn dir der Standardring nicht gefällt, ersetz ihn durch einen schöneren, aber lass ihn nicht weg.

:user-invalid statt :invalid

invalid gegen user-invalid
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 24px;
  font-family: system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.5;
}

.etikett {
  margin: 0 0 8px 0;
  font-size: 14px;
  color: #52525b;
}

p {
  margin: 0 0 24px 0;
}

input {
  width: 280px;
  padding: 10px 12px;
  border: 2px solid #d4d4d8;
  border-radius: 8px;
  font: inherit;
}

.frueh:invalid {
  border-color: #b91c1c;
  background-color: #fef2f2;
}

.spaet:user-invalid {
  border-color: #b91c1c;
  background-color: #fef2f2;
}

.hinweis {
  max-width: 60ch;
  color: #52525b;
}

:invalid trifft, sobald der Wert nicht passt, und ein leeres Pflichtfeld passt nun einmal nicht. Ein Formular mit :invalid-Styling leuchtet deshalb schon rot, bevor jemand ein Zeichen getippt hat, und das liest sich als Vorwurf für etwas, das man noch gar nicht falsch machen konnte.

:user-invalid wartet, bis der Mensch das Feld wirklich bearbeitet und wieder verlassen hat. Erst dann meldet es. Das Gegenstück heißt :user-valid und darf die grüne Rückmeldung geben.

Der Unterschied steht im Streifen, ohne dass du ein Zeichen tippen musst. Am oberen Feld: border: 2px solid rgb(185, 28, 28) und background-color: rgb(254, 242, 242), also rot, obwohl noch niemand etwas falsch gemacht hat. Am unteren: border: 2px solid rgb(212, 212, 216) und Weiß. Tipp danach eine unvollständige Adresse in das untere Feld und klick daneben, dann wechselt es die Farbe, und du siehst im Streifen dieselben Werte wie oben.

Nimm für die Rückmeldung nie nur die Farbe. Rot allein sehen Menschen mit Rotsehschwäche nicht, und ein Rahmen plus ein Text daneben kostet dich nichts.

Der Rest, den man selten braucht und ab und zu doch

::placeholder färbt den Platzhaltertext. Achte darauf, ihn nicht zu blass zu machen: Er ist Dekoration, aber lesbar sollte er bleiben. Und er ist kein Ersatz für ein Label, denn er verschwindet beim Tippen, und danach weiß niemand mehr, was in das Feld gehörte.

resize: vertical an textarea erlaubt das Größerziehen nach unten und verbietet es zur Seite. Ohne diese Zeile kann jeder das Layout seitlich sprengen, und irgendwer macht es.

field-sizing: content lässt ein Feld mit seinem Inhalt mitwachsen, statt eine feste Zeilenzahl zu behalten. Neu genug, dass es noch nicht überall geht, also als Verbesserung einsetzen und nicht als Grundlage.

Zum Mitnehmen

Bei einem Formular ist Gestaltung nie nur Geschmack. Jede Entscheidung hier entscheidet mit darüber, ob jemand das Formular ausfüllt oder aufgibt, und die meisten Fehler kosten nicht Schönheit, sondern Bedienbarkeit.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.