Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

UI-Pseudoklassen

In den vorherigen Artikeln haben wir das Styling verschiedener Formular-Steuerelemente allgemein behandelt. Dazu gehörte auch die Verwendung von Pseudoklassen, beispielsweise die Verwendung von :checked, um ein Kontrollkästchen nur dann anzusprechen, wenn es ausgewählt ist. In diesem Artikel untersuchen wir die verschiedenen UI-Pseudoklassen, die zum Styling von Formularen in unterschiedlichen Zuständen verfügbar sind.

Voraussetzungen: Grundlegende Kenntnisse von HTML und CSS, einschließlich allgemeiner Kenntnisse über Pseudoklassen und Pseudoelemente.
Ziel: Verstehen, welche Teile von Formularen schwierig zu stylen sind und warum; lernen, was getan werden kann, um sie anzupassen.

Welche Pseudoklassen stehen uns zur Verfügung?

Möglicherweise kennen Sie bereits die folgenden Pseudoklassen:

  • :hover: Wählt ein Element nur aus, wenn sich ein Mauszeiger darüber befindet.
  • :focus: Wählt ein Element nur aus, wenn es fokussiert ist (d.h. wenn es über die Tastatur mit der Tabulatortaste erreicht wurde).
  • :active: Wählt ein Element nur aus, wenn es aktiviert wird (d.h. während darauf geklickt wird oder, bei einer Tastaturaktivierung, während die Taste Return / Enter gedrückt wird).

CSS-Selektoren bieten mehrere weitere Pseudoklassen im Zusammenhang mit HTML-Formularen. Diese stellen mehrere nützliche Auswahlbedingungen bereit, die Sie nutzen können. In den folgenden Abschnitten besprechen wir sie ausführlicher, doch kurz zusammengefasst sind die wichtigsten, die wir betrachten werden:

  • :required und :optional: Sprechen Elemente an, die erforderlich sein können (z. B. Elemente, die das HTML-Attribut required unterstützen), je nachdem, ob sie erforderlich oder optional sind.
  • :valid und :invalid sowie :in-range und :out-of-range: Sprechen Formular-Steuerelemente an, die gemäß den für sie festgelegten Formularvalidierungsbedingungen gültig/ungültig oder innerhalb/außerhalb des Bereichs liegen.
  • :enabled und :disabled sowie :read-only und :read-write: Sprechen Elemente an, die deaktiviert werden können (z. B. Elemente, die das HTML-Attribut disabled unterstützen), je nachdem, ob sie aktuell aktiviert oder deaktiviert sind, sowie Formular-Steuerelemente mit Lese-/Schreibzugriff oder nur Lesezugriff (z. B. Elemente mit gesetztem Attribut readonly).
  • :checked, :indeterminate und :default: Sprechen jeweils Kontrollkästchen und Optionsfelder an, die aktiviert sind, sich in einem unbestimmten Zustand befinden (weder aktiviert noch deaktiviert) und die standardmäßig ausgewählte Option beim Laden der Seite darstellen (z. B. ein <input type="checkbox"> mit gesetztem Attribut checked oder ein <option>-Element mit gesetztem Attribut selected).

Es gibt viele weitere, aber die oben aufgeführten sind am offensichtlichsten nützlich. Einige von ihnen sind auf die Lösung sehr spezifischer Nischenprobleme ausgerichtet. Die oben aufgeführten UI-Pseudoklassen verfügen über eine ausgezeichnete Browser-Unterstützung, aber natürlich sollten Sie Ihre Formularimplementierungen sorgfältig testen, um sicherzustellen, dass sie für Ihre Zielgruppe funktionieren.

Hinweis: Einige der hier behandelten Pseudoklassen betreffen das Styling von Formular-Steuerelementen anhand ihres Validierungsstatus (sind ihre Daten gültig oder nicht?). Im nächsten Artikel — Formularvalidierung auf der Client-Seite — erfahren Sie viel mehr über das Festlegen und Steuern von Validierungsbedingungen. Vorerst halten wir die Formularvalidierung jedoch einfach, damit sie nicht für Verwirrung sorgt.

Eingaben danach stylen, ob sie erforderlich sind oder nicht

Eines der grundlegendsten Konzepte bei der Formularvalidierung auf der Client-Seite ist, ob eine Formulareingabe erforderlich ist (sie muss ausgefüllt werden, bevor das Formular übermittelt werden kann) oder optional.

<input>, <select> und <textarea>-Elemente verfügen über ein required-Attribut. Wenn dieses gesetzt ist, müssen Sie dieses Steuerelement ausfüllen, bevor das Formular erfolgreich übermittelt wird. Im folgenden Formular sind beispielsweise Vorname und Nachname erforderlich, die E-Mail-Adresse ist jedoch optional:

html
<form>
  <fieldset>
    <legend>Feedback form</legend>
    <div>
      <label for="fname">First name: </label>
      <input id="fname" name="fname" type="text" required />
    </div>
    <div>
      <label for="lname">Last name: </label>
      <input id="lname" name="lname" type="text" required />
    </div>
    <div>
      <label for="email"> Email address (if you want a response): </label>
      <input id="email" name="email" type="email" />
    </div>
    <div><button>Submit</button></div>
  </fieldset>
</form>

Sie können diese beiden Zustände mit den Pseudoklassen :required und :optional abgleichen. Wenn wir beispielsweise das folgende CSS auf das obige HTML anwenden:

css
input:required {
  border: 2px solid;
}

input:optional {
  border: 2px dashed;
}

Die erforderlichen Steuerelemente haben einen durchgehenden Rahmen, während das optionale Steuerelement einen gestrichelten Rahmen hat. Sie können auch versuchen, das Formular ohne Eingaben zu übermitteln, um die standardmäßigen Validierungsfehlermeldungen auf der Client-Seite zu sehen, die Browser anzeigen:

Im Allgemeinen sollten Sie in Formularen erforderliche gegenüber optionalen Elementen nicht ausschließlich mithilfe von Farben stylen, da dies für farbenblinde Menschen nicht ideal ist:

css
input:required {
  border: 2px solid red;
}

input:optional {
  border: 2px solid green;
}

Die übliche Konvention im Web für den Status „erforderlich“ ist ein Sternchen (*) oder das Wort „erforderlich“ in Verbindung mit den jeweiligen Steuerelementen. Im nächsten Abschnitt betrachten wir ein besseres Beispiel zum Kennzeichnen erforderlicher Felder mit :required und generiertem Inhalt.

Hinweis: Wahrscheinlich werden Sie die Pseudoklasse :optional nicht sehr häufig verwenden. Formular-Steuerelemente sind standardmäßig optional. Sie könnten Ihr Styling für optionale Elemente daher einfach als Standard festlegen und dann Styles für erforderliche Steuerelemente hinzufügen.

Hinweis: Wenn ein Optionsfeld in einer Gruppe gleichnamiger Optionsfelder das Attribut required gesetzt hat, sind alle Optionsfelder ungültig, bis eines ausgewählt wird. Allerdings entspricht nur das Feld, dem das Attribut zugewiesen wurde, tatsächlich :required.

Generierten Inhalt mit Pseudoklassen verwenden

In vorherigen Artikeln haben wir die Verwendung von generiertem Inhalt gesehen, aber wir dachten, jetzt wäre ein guter Zeitpunkt, etwas ausführlicher darüber zu sprechen.

Die Idee besteht darin, dass wir die Pseudoelemente ::before und ::after zusammen mit der Eigenschaft content verwenden können, um einen Inhaltsabschnitt vor oder nach dem betroffenen Element erscheinen zu lassen. Der Inhaltsabschnitt wird nicht zum DOM hinzugefügt und kann daher für einige Screenreader unsichtbar sein. Da es sich um ein Pseudoelement handelt, kann es auf dieselbe Weise mit Styles angesprochen werden wie jeder tatsächliche DOM-Knoten.

Dies ist besonders nützlich, wenn Sie einem Element einen visuellen Indikator wie ein Label oder ein Symbol hinzufügen möchten und gleichzeitig alternative Indikatoren verfügbar sind, um die Barrierefreiheit für alle Benutzenden sicherzustellen. Beispielsweise können wir generierten Inhalt verwenden, um die Platzierung und Animation des inneren Kreises einer benutzerdefinierten Schaltfläche zu handhaben, wenn ein Optionsfeld ausgewählt wird:

css
input[type="radio"]::before {
  display: block;
  content: " ";
  width: 10px;
  height: 10px;
  border-radius: 6px;
  background-color: red;
  font-size: 1.2em;
  transform: translate(3px, 3px) scale(0);
  transform-origin: center;
  transition: all 0.3s ease-in;
}

input[type="radio"]:checked::before {
  transform: translate(3px, 3px) scale(1);
  transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
}

Dies ist sehr nützlich — Screenreader teilen ihren Benutzenden bereits mit, wenn ein angetroffenes Optionsfeld oder Kontrollkästchen aktiviert/ausgewählt ist. Sie möchten daher nicht, dass sie ein weiteres DOM-Element vorlesen, das die Auswahl kennzeichnet, denn das könnte verwirrend sein. Ein rein visueller Indikator löst dieses Problem.

Nicht alle <input>-Typen unterstützen das Einfügen generierten Inhalts. Alle Eingabetypen, die dynamischen Text anzeigen, wie text, password oder button, zeigen keinen generierten Inhalt an. Andere, einschließlich range, color, checkbox usw., zeigen generierten Inhalt an.

Zurück zu unserem vorherigen Beispiel für erforderlich/optional: Dieses Mal verändern wir nicht das Aussehen der Eingabe selbst — wir verwenden generierten Inhalt, um ein kennzeichnendes Label hinzuzufügen.

Zunächst fügen wir am Anfang des Formulars einen Absatz hinzu, der erklärt, wonach Sie suchen:

html
<p>Required fields are labeled with "required".</p>

Benutzende von Screenreadern hören „erforderlich“ als zusätzliche Information, wenn sie jede erforderliche Eingabe erreichen, während sehende Benutzende unser Label sehen.

Wie bereits erwähnt, unterstützen Texteingaben keinen generierten Inhalt. Daher fügen wir ein leeres <span> hinzu, an dem der generierte Inhalt angehängt werden kann:

html
<div>
  <label for="fname">First name: </label>
  <input id="fname" name="fname" type="text" required />
  <span></span>
</div>

Das unmittelbare Problem dabei war, dass das span in eine neue Zeile unterhalb der Eingabe rutschte, weil die Eingabe und das Label beide mit width: 100% festgelegt sind. Um dies zu beheben, stylen wir das übergeordnete <div> als Flex-Container, teilen ihm aber auch mit, dass es seinen Inhalt in neue Zeilen umbrechen soll, falls der Inhalt zu lang wird:

css
fieldset > div {
  margin-bottom: 20px;
  display: flex;
  flex-flow: row wrap;
}

Dadurch befinden sich das Label und die Eingabe in getrennten Zeilen, da beide width: 100% haben. Das <span> hat jedoch eine Breite von 0 und kann daher in derselben Zeile wie die Eingabe stehen.

Kommen wir nun zum generierten Inhalt. Wir erstellen ihn mit diesem CSS:

css
input + span {
  position: relative;
}

input:required + span::after {
  font-size: 0.7rem;
  position: absolute;
  content: "required";
  color: white;
  background-color: black;
  padding: 5px 10px;
  top: -26px;
  left: -70px;
}

Wir setzen für das <span> position: relative, damit wir für den generierten Inhalt position: absolute festlegen und ihn relativ zum <span> statt zum <body> positionieren können. (Der generierte Inhalt verhält sich bei der Positionierung so, als wäre er ein Kindknoten des Elements, auf dem er generiert wird.)

Dann geben wir dem generierten Inhalt den Text „erforderlich“, was unser Label aussagen sollte, und stylen und positionieren ihn wie gewünscht. Das Ergebnis sehen Sie unten (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten).

Steuerelemente danach stylen, ob ihre Daten gültig sind

Das andere sehr wichtige, grundlegende Konzept der Formularvalidierung ist, ob die Daten eines Formular-Steuerelements gültig sind oder nicht (bei numerischen Daten können wir auch über Daten innerhalb oder außerhalb des Bereichs sprechen). Formular-Steuerelemente mit Einschränkungsbedingungen können anhand dieser Zustände angesprochen werden.

:valid und :invalid

Sie können Formular-Steuerelemente mit den Pseudoklassen :valid und :invalid ansprechen. Einige Punkte, die Sie beachten sollten:

  • Steuerelemente ohne Einschränkungsvalidierung sind immer gültig und entsprechen daher :valid.
  • Steuerelemente mit gesetztem required, die keinen Wert haben, gelten als ungültig — sie entsprechen :invalid und :required.
  • Steuerelemente mit integrierter Validierung, wie <input type="email"> oder <input type="url">, entsprechen :invalid, wenn die eingegebenen Daten nicht dem erwarteten Muster entsprechen (sind jedoch gültig, wenn sie leer sind).
  • Steuerelemente, deren aktueller Wert außerhalb der durch die Attribute min und max angegebenen Bereichsgrenzen liegt, entsprechen :invalid, werden aber auch von :out-of-range erfasst, wie Sie später sehen werden.
  • Es gibt einige weitere Möglichkeiten, ein Element mit :valid/:invalid abzugleichen, wie Sie im Artikel Formularvalidierung auf der Client-Seite sehen werden. Vorerst halten wir es jedoch einfach.

Schauen wir uns ein Beispiel für :valid/:invalid an.

Wie im vorherigen Beispiel haben wir zusätzliche <span>-Elemente, auf denen Inhalt generiert wird. Wir verwenden sie, um Indikatoren für gültige/ungültige Daten bereitzustellen:

html
<div>
  <label for="fname">First name: </label>
  <input id="fname" name="fname" type="text" required />
  <span></span>
</div>

Um diese Indikatoren bereitzustellen, verwenden wir das folgende CSS:

css
input + span {
  position: relative;
}

input + span::before {
  position: absolute;
  right: -20px;
  top: 5px;
}

input:invalid {
  border: 2px solid red;
}

input:invalid + span::before {
  content: "✖";
  color: red;
}

input:valid + span::before {
  content: "✓";
  color: green;
}

Wie zuvor setzen wir für die <span>-Elemente position: relative, damit wir den generierten Inhalt relativ zu ihnen positionieren können. Anschließend positionieren wir unterschiedlichen generierten Inhalt absolut, je nachdem, ob die Daten des Formulars gültig oder ungültig sind — jeweils ein grünes Häkchen oder ein rotes Kreuz. Um den ungültigen Daten etwas mehr Dringlichkeit zu verleihen, haben wir den Eingaben bei Ungültigkeit außerdem einen dicken roten Rahmen gegeben.

Hinweis: Wir haben ::before verwendet, um diese Labels hinzuzufügen, da wir ::after bereits für die Labels „erforderlich“ verwenden.

Sie können es unten ausprobieren (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten):

Beachten Sie, dass die erforderlichen Texteingaben ungültig sind, wenn sie leer sind, aber gültig, wenn sie ausgefüllt wurden. Die E-Mail-Eingabe hingegen ist gültig, wenn sie leer ist, da sie nicht erforderlich ist, aber ungültig, wenn sie etwas enthält, das keine korrekte E-Mail-Adresse ist.

Daten innerhalb und außerhalb des Bereichs

Wie oben angedeutet, gibt es zwei weitere verwandte Pseudoklassen — :in-range und :out-of-range. Diese entsprechen numerischen Eingaben, deren Bereichsgrenzen durch min und max angegeben werden, wenn sich ihre Daten jeweils innerhalb oder außerhalb des angegebenen Bereichs befinden.

Hinweis: Numerische Eingabetypen sind date, month, week, time, datetime-local, number und range.

Es ist wichtig zu beachten, dass Eingaben mit Daten innerhalb des Bereichs auch der Pseudoklasse :valid entsprechen und Eingaben mit Daten außerhalb des Bereichs auch der Pseudoklasse :invalid. Warum gibt es also beide? Das Problem betrifft hauptsächlich die Semantik — außerhalb des Bereichs ist eine spezifischere Art, Ungültigkeit zu kommunizieren. Daher möchten Sie für Eingaben außerhalb des Bereichs möglicherweise eine andere Meldung bereitstellen, die für Benutzende hilfreicher ist als lediglich „ungültig“. Möglicherweise möchten Sie sogar beide bereitstellen.

Schauen wir uns ein Beispiel an, das genau dies tut. Es baut auf dem vorherigen Beispiel auf, um Meldungen für numerische Eingaben außerhalb des Bereichs bereitzustellen und gleichzeitig anzugeben, ob diese erforderlich sind.

Die numerische Eingabe sieht folgendermaßen aus:

html
<div>
  <label for="age">Age (must be 12+): </label>
  <input id="age" name="age" type="number" min="12" max="120" required />
  <span></span>
</div>

Und das CSS sieht so aus:

css
input + span {
  position: relative;
}

input + span::after {
  font-size: 0.7rem;
  position: absolute;
  padding: 5px 10px;
  top: -26px;
}

input:required + span::after {
  color: white;
  background-color: black;
  content: "Required";
  left: -70px;
}

input:out-of-range + span::after {
  color: white;
  background-color: red;
  width: 155px;
  content: "Outside allowable value range";
  left: -182px;
}

Dies ähnelt dem vorherigen Beispiel für :required, außer dass wir hier die Deklarationen, die für beliebigen ::after-Inhalt gelten, in eine separate Regel aufgeteilt haben und dem separaten ::after-Inhalt für die Zustände :required und :out-of-range jeweils eigenen Inhalt und eigenes Styling geben. Sie können es hier ausprobieren (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten):

Es ist möglich, dass die Zahleneingabe gleichzeitig erforderlich und außerhalb des Bereichs ist. Was passiert dann? Da die Regel :out-of-range im Quellcode später erscheint als die Regel :required, kommen die Kaskadenregeln zum Tragen und die Meldung außerhalb des Bereichs wird angezeigt.

Das funktioniert ziemlich gut — beim ersten Laden der Seite wird „Erforderlich“ zusammen mit einem roten Kreuz und Rahmen angezeigt. Wenn Sie ein gültiges Alter eingeben (d.h. im Bereich von 12 bis 120), wird die Eingabe gültig. Wenn Sie den Alterseintrag anschließend in einen Wert außerhalb des Bereichs ändern, erscheint die Meldung „Außerhalb des zulässigen Wertebereichs“ anstelle von „Erforderlich“.

Hinweis: Um einen ungültigen Wert bzw. einen Wert außerhalb des Bereichs einzugeben, müssen Sie das Formular tatsächlich fokussieren und ihn über die Tastatur eingeben. Die Spinner-Schaltflächen erlauben es Ihnen nicht, den Wert über den zulässigen Bereich hinaus zu erhöhen oder zu verringern.

Aktivierte und deaktivierte Eingaben sowie schreibgeschützte und beschreibbare Eingaben stylen

Ein aktiviertes Element ist ein Element, das aktiviert werden kann; es kann ausgewählt, angeklickt, beschrieben usw. werden. Mit einem deaktivierten Element kann hingegen in keiner Weise interagiert werden, und seine Daten werden nicht einmal an den Server gesendet.

Diese beiden Zustände können mit :enabled und :disabled angesprochen werden. Warum sind deaktivierte Eingaben nützlich? Wenn einige Daten für eine bestimmte Person nicht zutreffen, möchten Sie diese Daten möglicherweise gar nicht übermitteln, wenn das Formular übermittelt wird. Ein klassisches Beispiel ist ein Versandformular — häufig werden Sie gefragt, ob Sie dieselbe Adresse für Rechnungs- und Versandadresse verwenden möchten. Wenn ja, können Sie einfach eine einzige Adresse an den Server senden und die Felder für die Rechnungsadresse deaktivieren.

Schauen wir uns ein Beispiel an, das genau dies tut. Das HTML ist zunächst ein einfaches Formular mit Texteingaben sowie einem Kontrollkästchen, mit dem die Deaktivierung der Rechnungsadresse ein- und ausgeschaltet wird. Die Felder für die Rechnungsadresse sind standardmäßig deaktiviert.

html
<form>
  <fieldset id="shipping">
    <legend>Shipping address</legend>
    <div>
      <label for="name1">Name: </label>
      <input id="name1" name="name1" type="text" required />
    </div>
    <div>
      <label for="address1">Address: </label>
      <input id="address1" name="address1" type="text" required />
    </div>
    <div>
      <label for="zip-code1">Zip/postal code: </label>
      <input id="zip-code1" name="zip-code1" type="text" required />
    </div>
  </fieldset>
  <fieldset id="billing">
    <legend>Billing address</legend>
    <div>
      <label for="billing-checkbox">Same as shipping address:</label>
      <input type="checkbox" id="billing-checkbox" checked />
    </div>
    <div>
      <label for="name" class="billing-label disabled-label">Name: </label>
      <input id="name" name="name" type="text" disabled required />
    </div>
    <div>
      <label for="address2" class="billing-label disabled-label">
        Address:
      </label>
      <input id="address2" name="address2" type="text" disabled required />
    </div>
    <div>
      <label for="zip-code2" class="billing-label disabled-label">
        Zip/postal code:
      </label>
      <input id="zip-code2" name="zip-code2" type="text" disabled required />
    </div>
  </fieldset>

  <div><button>Submit</button></div>
</form>

Kommen wir nun zum CSS. Die relevantesten Teile dieses Beispiels sind die folgenden:

css
input[type="text"]:disabled {
  background: #eeeeee;
  border: 1px solid #cccccc;
}

label:has(+ :disabled) {
  color: #aaaaaa;
}

Wir haben die Eingaben, die wir deaktivieren möchten, direkt mit input[type="text"]:disabled ausgewählt, wollten aber auch die entsprechenden Textlabels ausgrauen. Da die Labels direkt vor ihren Eingaben stehen, haben wir sie mit der Pseudoklasse :has ausgewählt.

Abschließend haben wir JavaScript verwendet, um die Deaktivierung der Felder für die Rechnungsadresse umzuschalten:

js
function toggleBilling() {
  // Select the billing text fields
  const billingItems = document.querySelectorAll('#billing input[type="text"]');

  // Toggle the billing text fields
  for (const item of billingItems) {
    item.disabled = !item.disabled;
  }
}

// Attach `change` event listener to checkbox
document
  .getElementById("billing-checkbox")
  .addEventListener("change", toggleBilling);

Dabei wird das change-Ereignis verwendet, damit Benutzende die Rechnungsfelder aktivieren/deaktivieren und das Styling der zugehörigen Labels umschalten können.

Sie können das Beispiel unten in Aktion sehen (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten):

Schreibgeschützt und beschreibbar

Ähnlich wie :disabled und :enabled sprechen die Pseudoklassen :read-only und :read-write zwei Zustände an, zwischen denen Formulareingaben wechseln. Wie bei deaktivierten Eingaben können Benutzende schreibgeschützte Eingaben nicht bearbeiten. Anders als bei deaktivierten Eingaben werden Werte schreibgeschützter Eingaben jedoch an den Server übermittelt. Read-write bedeutet, dass sie bearbeitet werden können — ihr Standardzustand.

Eine Eingabe wird mit dem Attribut readonly auf schreibgeschützt gesetzt. Stellen Sie sich beispielsweise eine Bestätigungsseite vor, auf die die Entwicklerin oder der Entwickler die auf vorherigen Seiten ausgefüllten Daten übertragen hat. Die Benutzenden sollen alle Angaben an einer Stelle überprüfen, eventuell benötigte abschließende Daten ergänzen und dann die Bestellung durch Übermitteln bestätigen. Zu diesem Zeitpunkt können alle endgültigen Formulardaten auf einmal an den Server gesendet werden.

Schauen wir uns an, wie ein Formular aussehen könnte.

Ein Ausschnitt des HTML sieht folgendermaßen aus — beachten Sie das Attribut readonly:

html
<div>
  <label for="name">Name: </label>
  <input id="name" name="name" type="text" value="Mr Soft" readonly />
</div>

Wenn Sie das Live-Beispiel ausprobieren, sehen Sie, dass der obere Satz an Formularelementen nicht bearbeitbar ist, die Werte beim Übermitteln des Formulars jedoch übermittelt werden. Wir haben die Formular-Steuerelemente mit den Pseudoklassen :read-only und :read-write folgendermaßen gestylt:

css
input:read-only,
textarea:read-only {
  border: 0;
  box-shadow: none;
  background-color: white;
}

textarea:read-write {
  box-shadow: inset 1px 1px 3px #cccccc;
  border-radius: 5px;
}

Das vollständige Beispiel sieht so aus (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten):

Hinweis: :enabled und :read-write sind zwei weitere Pseudoklassen, die Sie wahrscheinlich selten verwenden werden, da sie die Standardzustände von Eingabeelementen beschreiben.

Optionsfeld- und Kontrollkästchenzustände — aktiviert, Standard, unbestimmt

Wie wir in früheren Artikeln des Moduls gesehen haben, können Optionsfelder und Kontrollkästchen aktiviert oder deaktiviert sein. Es gibt jedoch noch einige weitere Zustände, die berücksichtigt werden müssen:

  • :default: Entspricht Optionsfeldern/Kontrollkästchen, die beim Laden der Seite standardmäßig aktiviert sind (d.h. durch Setzen des Attributs checked). Sie entsprechen der Pseudoklasse :default, selbst wenn Benutzende sie deaktivieren.
  • :indeterminate: Wenn Optionsfelder/Kontrollkästchen weder aktiviert noch deaktiviert sind, gelten sie als unbestimmt und entsprechen der Pseudoklasse :indeterminate. Weiter unten erfahren Sie mehr darüber, was dies bedeutet.

:checked

Wenn sie aktiviert sind, entsprechen sie der Pseudoklasse :checked.

Die häufigste Verwendung besteht darin, einem Kontrollkästchen oder Optionsfeld bei Aktivierung einen anderen Stil zu geben, wenn Sie das standardmäßige System-Styling mit appearance: none; entfernt haben und die Styles selbst wieder aufbauen möchten. Beispiele dafür haben wir im vorherigen Artikel gesehen, als wir über das Styling von Kontrollkästchen und Optionsfeldern mit appearance gesprochen haben.

Zur Wiederholung sieht der :checked-Code aus unserem Beispiel für gestylte Optionsfelder folgendermaßen aus:

css
input[type="radio"]::before {
  display: block;
  content: " ";
  width: 10px;
  height: 10px;
  border-radius: 6px;
  background-color: red;
  font-size: 1.2em;
  transform: translate(3px, 3px) scale(0);
  transform-origin: center;
  transition: all 0.3s ease-in;
}

input[type="radio"]:checked::before {
  transform: translate(3px, 3px) scale(1);
  transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
}

Sie können ihn hier ausprobieren (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten):

Im Grunde erstellen wir das Styling für den „inneren Kreis“ eines Optionsfelds mit dem Pseudoelement ::before, setzen darauf jedoch eine transform-Funktion scale(0). Anschließend verwenden wir eine transition, um den generierten Inhalt der Eingabe beim Auswählen/Aktivieren des Optionsfelds angenehm ins Blickfeld zu animieren. Der Vorteil der Verwendung einer Transformation anstelle einer Transition von width/height besteht darin, dass Sie transform-origin verwenden können, damit der Kreis von seiner Mitte aus wächst, statt scheinbar von seiner Ecke aus zu wachsen. Außerdem tritt kein Springen auf, da keine Eigenschaftswerte des Box-Modells aktualisiert werden.

:default und :indeterminate

Wie oben erwähnt, entspricht die Pseudoklasse :default Optionsfeldern/Kontrollkästchen, die beim Laden der Seite standardmäßig aktiviert sind, selbst wenn sie deaktiviert werden. Dies könnte nützlich sein, um einer Optionsliste einen Indikator hinzuzufügen, der Benutzende daran erinnert, welche die Standardoptionen (oder Ausgangsoptionen) waren, falls sie ihre Auswahl zurücksetzen möchten.

Außerdem entsprechen die oben genannten Optionsfelder/Kontrollkästchen der Pseudoklasse :indeterminate, wenn sie sich in einem Zustand befinden, in dem sie weder aktiviert noch deaktiviert sind. Was bedeutet das aber? Zu den unbestimmten Elementen gehören:

  • <input/radio>-Eingaben, wenn alle Optionsfelder in einer gleichnamigen Gruppe deaktiviert sind
  • <input/checkbox>-Eingaben, deren Eigenschaft indeterminate über JavaScript auf true gesetzt ist
  • <progress>-Elemente ohne Wert.

Dies werden Sie wahrscheinlich nicht sehr häufig verwenden. Ein Anwendungsfall könnte ein Indikator sein, der Benutzenden mitteilt, dass sie unbedingt ein Optionsfeld auswählen müssen, bevor sie fortfahren.

Schauen wir uns einige modifizierte Versionen des vorherigen Beispiels an, die Benutzende daran erinnern, welche die Standardoption war, und die Labels von Optionsfeldern im unbestimmten Zustand stylen. Beide verwenden die folgende HTML-Struktur für die Eingaben:

html
<p>
  <input type="radio" name="fruit" value="cherry" id="cherry" />
  <label for="cherry">Cherry</label>
  <span></span>
</p>

Für das Beispiel mit :default haben wir dem mittleren Optionsfeld-Eingabeelement das Attribut checked hinzugefügt, sodass es beim Laden standardmäßig ausgewählt wird. Anschließend stylen wir dies mit dem folgenden CSS:

css
input ~ span {
  position: relative;
}

input:default ~ span::after {
  font-size: 0.7rem;
  position: absolute;
  content: "Default";
  color: white;
  background-color: black;
  padding: 5px 10px;
  right: -65px;
  top: -3px;
}

Dadurch wird beim Element, das ursprünglich beim Laden der Seite ausgewählt war, ein kleines Label „Standard“ angezeigt. Beachten Sie, dass wir hier den nachfolgenden Geschwisterkombinator (~) statt des Kombinators für das nächste Geschwisterelement (+) verwenden — wir müssen dies tun, weil das <span> in der Quellreihenfolge nicht direkt nach dem <input> steht.

Sehen Sie das Live-Ergebnis unten (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten):

Für das Beispiel mit :indeterminate haben wir kein standardmäßig ausgewähltes Optionsfeld — das ist wichtig — denn wenn es eines gäbe, gäbe es keinen unbestimmten Zustand, der gestylt werden könnte. Wir stylen die unbestimmten Optionsfelder mit folgendem CSS:

css
input[type="radio"]:indeterminate {
  outline: 2px solid red;
  animation: 0.4s linear infinite alternate outline-pulse;
}

@keyframes outline-pulse {
  from {
    outline: 2px solid red;
  }

  to {
    outline: 6px solid red;
  }
}

Dadurch entsteht eine interessante kleine animierte Umrandung um die Optionsfelder, die hoffentlich verdeutlicht, dass Sie eines davon auswählen müssen!

Sehen Sie das Live-Ergebnis unten (drücken Sie die Schaltfläche Play, um das Beispiel in MDN Playground auszuführen und den Quellcode zu bearbeiten):

Hinweis: Auf der Referenzseite für <input type="checkbox"> finden Sie ein interessantes Beispiel mit indeterminate-Zuständen.

Weitere Pseudoklassen

Es gibt noch eine Reihe weiterer interessanter Pseudoklassen, und wir haben hier nicht genügend Platz, um alle ausführlich zu behandeln. Lassen Sie uns einige weitere besprechen, die Sie genauer untersuchen sollten.

  • Die Pseudoklasse :focus-within entspricht einem Element, das den Fokus erhalten hat oder ein Element enthält, das den Fokus erhalten hat. Dies ist nützlich, wenn ein gesamtes Formular auf irgendeine Weise hervorgehoben werden soll, sobald eine Eingabe darin fokussiert ist.
  • Die Pseudoklasse :focus-visible entspricht fokussierten Elementen, die den Fokus durch Tastaturinteraktion erhalten haben (statt durch Berührung oder Maus) — nützlich, wenn Sie für Tastaturfokus einen anderen Stil als für Mausfokus (oder anderen Fokus) anzeigen möchten.
  • Die Pseudoklasse :placeholder-shown entspricht <input>- und <textarea>-Elementen, deren Platzhalter angezeigt wird (d.h. der Inhalt des Attributs placeholder), weil der Wert des Elements leer ist.

Die folgenden sind ebenfalls interessant, werden jedoch bislang nicht gut von Browsern unterstützt:

  • Die Pseudoklasse :blank wählt leere Formular-Steuerelemente aus. :empty entspricht ebenfalls Elementen ohne Kindelemente, wie <input>, ist jedoch allgemeiner — sie entspricht auch anderen leeren Elementen wie <br> und <hr>. :empty wird von Browsern angemessen unterstützt; die Spezifikation der Pseudoklasse :blank ist noch nicht abgeschlossen und wird daher von keinem Browser unterstützt.
  • Die Pseudoklasse :user-invalid wird, sofern unterstützt, ähnlich wie :invalid sein, aber mit einer besseren Benutzererfahrung. Wenn der Wert gültig ist, sobald die Eingabe den Fokus erhält, kann das Element während der Eingabe durch die Benutzenden :invalid entsprechen, wenn der Wert vorübergehend ungültig ist. Es entspricht jedoch erst :user-invalid, wenn das Element den Fokus verliert. Wenn der Wert ursprünglich ungültig war, entspricht es während der gesamten Fokusdauer sowohl :invalid als auch :user-invalid. Ähnlich wie bei :invalid entspricht es nicht mehr :user-invalid, wenn der Wert gültig wird.

Zusammenfassung

Damit ist unser Überblick über UI-Pseudoklassen abgeschlossen, die sich auf Formulareingaben beziehen. Experimentieren Sie weiter damit und erstellen Sie ansprechende Formular-Styles! Als Nächstes widmen wir uns einem anderen Thema — der Formularvalidierung auf der Client-Seite.