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 die Gestaltung verschiedener Formularelemente auf allgemeine Weise behandelt. Dies beinhaltete die Verwendung von Pseudoklassen, zum Beispiel die Verwendung von :checked, um ein Kontrollkästchen nur dann zu selektieren, wenn es ausgewählt ist. In diesem Artikel erkunden wir die verschiedenen verfügbaren UI-Pseudoklassen zur Gestaltung von Formularen in unterschiedlichen Zuständen.

Voraussetzungen: Ein grundlegendes Verständnis von HTML und CSS, einschließlich allgemeiner Kenntnisse über Pseudoklassen und Pseudoelemente.
Ziel: Verstehen, welche Teile von Formularen schwer zu gestalten sind und warum; lernen, was getan werden kann, um sie anzupassen.

Welche Pseudoklassen haben wir zur Verfügung?

Sie sind möglicherweise bereits mit den folgenden Pseudoklassen vertraut:

  • :hover: Selektiert ein Element nur, wenn es von einem Mauszeiger überfahren wird.
  • :focus: Selektiert ein Element nur, wenn es fokussiert ist (d.h. wenn es z.B. über die Tastatur angesteuert wird).
  • :active: Selektiert ein Element nur, wenn es aktiviert wird (d.h. während es angeklickt wird oder wenn die Return / Enter-Taste bei einer Tastaturaktivierung gedrückt gehalten wird).

CSS-Selektoren bieten mehrere weitere Pseudoklassen, die sich auf HTML-Formulare beziehen. Diese bieten verschiedene nützliche Zielbedingungen, die Sie nutzen können. Wir werden diese später im Text ausführlicher besprechen, aber kurz gesagt, die wichtigsten davon sind:

  • :required und :optional: Ziel sind Elemente, die erforderlich sein können (z.B. Elemente, die das required HTML-Attribut unterstützen)), basierend darauf, ob sie erforderlich oder optional sind.
  • :valid und :invalid, und :in-range und :out-of-range: Ziel sind Formularelemente, die gemäß ihren Formularvalidierungsbeschränkungen gültig/ungültig sind oder im Bereich/außerhalb des Bereichs liegen.
  • :enabled und :disabled, und :read-only und :read-write: Ziel ist die Elemente, die deaktiviert sein können (z.B. Elemente, die das disabled HTML-Attribut unterstützen), basierend darauf, ob sie derzeit aktiviert oder deaktiviert sind, und schreibgeschützte oder schreibbare Formularelemente (z.B. Elemente mit dem readonly HTML-Attribut).
  • :checked, :indeterminate, und :default: Ziel sind Kontrollkästchen und Optionsfelder, die ausgewählt, in einem unbestimmten Zustand (weder ausgewählt noch nicht ausgewählt) und als Standardoption beim Laden der Seite gesetzt sind (z.B. ein <input type="checkbox"> mit dem checked-Attribut oder ein <option> Element mit dem selected-Attribut).

Es gibt viele andere, aber die oben aufgeführten sind am offensichtlichsten nützlich. Einige von ihnen sind darauf ausgerichtet, sehr spezifische Nischenprobleme zu lösen. Die oben aufgeführten UI-Pseudoklassen haben eine hervorragende Browser-Kompatibilität, aber natürlich sollten Sie Ihre Formularimplementierungen sorgfältig testen, um sicherzustellen, dass sie für Ihr Zielpublikum funktionieren.

Hinweis: Einige der hier besprochenen Pseudoklassen befassen sich mit der Gestaltung von Formularelementen basierend auf ihrem Validierungszustand (ist ihre Eingabe gültig oder nicht?). Sie werden in unserem nächsten Artikel viel mehr über das Setzen und Kontrollieren von Validierungsbeschränkungen lernen — Client-seitige Formularvalidierung — aber für jetzt halten wir die Dinge einfach bezüglich der Formularvalidierung, damit es nicht verwirrt.

Eingaben basierend darauf gestalten, ob sie erforderlich sind oder nicht

Eines der grundlegendsten Konzepte bezüglich der Client-seitigen Formularvalidierung ist, ob eine Formulareingabe erforderlich ist (sie muss ausgefüllt werden, bevor das Formular gesendet werden kann) oder optional.

<input>, <select>, und <textarea> Elemente haben ein verfügbares required-Attribut, das, wenn gesetzt, bedeutet, dass Sie dieses Element ausfüllen müssen, bevor das Formular erfolgreich gesendet wird. Zum Beispiel sind im folgenden Formular der Vorname und Nachname erforderlich, aber die E-Mail-Adresse ist 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 :required und :optional Pseudoklassen abgleichen. Zum Beispiel, wenn wir 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 Rand, und das optionale Steuerelement hat einen gestrichelten Rand. Sie können auch versuchen, das Formular zu senden, ohne es auszufüllen, um die client-seitigen Validierungsfehlermeldungen zu sehen, die Ihnen die Browser standardmäßig geben:

Im Allgemeinen sollten Sie vermeiden, 'erforderliche' gegenüber 'optionalen' Elementen in Formularen nur mit Farbe zu gestalten, da dies für farbenblinde Menschen nicht ideal ist:

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

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

Der Standard auf dem Web zur Angabe des Erfordernisses ist ein Sternchen (*) oder das Wort "erforderlich", das mit den jeweiligen Steuerelementen verknüpft ist. Im nächsten Abschnitt schauen wir uns ein besseres Beispiel an, wie erforderliche Felder unter Verwendung von :required und generiertem Inhalt angezeigt werden können.

Hinweis: Sie werden die :optional-Pseudoklasse wahrscheinlich nicht oft verwenden. Formularsteuerelemente sind standardmäßig optional, sodass Sie Ihre optionale Gestaltung einfach standardmäßig vornehmen können und für erforderliche Steuerelemente zusätzliche Stile hinzufügen.

Hinweis: Wenn ein einzelnes Kontrollkästchen in einer gleichnamigen Gruppe von Kontrollkästchen das required-Attribut gesetzt hat, sind alle Kontrollkästchen ungültig, bis eines ausgewählt ist, aber nur das, dem das Attribut zugewiesen ist, wird tatsächlich mit :required abgeglichen.

Verwendung von generiertem Inhalt mit Pseudoklassen

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

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

Dies ist wirklich nützlich, wenn Sie einem Element einen visuellen Indikator hinzufügen möchten, wie beispielsweise ein Etikett oder Symbol, während alternative Indikatoren ebenfalls verfügbar sind, um die Zugänglichkeit für alle Benutzer zu gewährleisten. Beispielsweise können wir generierten Inhalt verwenden, um die Platzierung und Animation des inneren Kreises des benutzerdefinierten Auswahlknopfes zu steuern, wenn ein Auswahlknopf aktiviert 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 wirklich nützlich — Screenreader lassen ihre Benutzer bereits wissen, wann ein von ihnen gefundenes Kontrollkästchen oder Auswahlknopf aktiviert/ausgewählt ist, sodass Sie nicht möchten, dass sie ein weiteres DOM-Element vorlesen, das die Auswahl anzeigt — das könnte verwirrend sein. Einen rein visuellen Indikator zu haben, löst dieses Problem.

Nicht alle <input>-Typen unterstützen das Platzieren von generiertem Inhalt auf ihnen. Alle Eingabetypen, die dynamischen Text in sich anzeigen, wie text, password oder button, zeigen keinen generierten Inhalt an. Andere, einschließlich range, color, checkbox, etc., zeigen generierten Inhalt an.

Zurück zu unserem Beispiel von erforderlichen/optional Elementen von zuvor, diesmal ändern wir nicht das Erscheinungsbild der Eingabe selbst — wir verwenden generierten Inhalt, um ein anzeigendes Etikett hinzuzufügen.

Zuerst fügen wir einen Absatz an die Spitze des Formulars hinzu, der das angibt, was Sie suchen:

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

Benutzer von Screenreadern bekommen beim Erreichen eines erforderlichen Eingabefelds "erforderlich" vorgelesen, während sehfähige Benutzer unser Etikett sehen.

Wie bereits erwähnt, unterstützen Texteingaben keinen generierten Inhalt, daher fügen wir ein leeres <span> hinzu, um den generierten Inhalt daran zu befestigen:

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 der span in eine neue Zeile unterhalb der Eingabe gerutscht ist, weil sowohl die Eingabe als auch das Etikett auf width: 100% gesetzt sind. Um dies zu beheben, gestalten wir das übergeordnete <div> zu einem Flex-Container um, sagen ihm jedoch, dass er seinen Inhalt auf neue Zeilen umbricht, wenn der Inhalt zu lang wird:

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

Die Wirkung dessen ist, dass das Etikett und die Eingabe auf separaten Zeilen sitzen, weil sie beide width: 100% haben, aber das <span> hat eine Breite von 0, sodass es auf die gleiche Zeile wie die Eingabe passen kann.

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 das <span> auf position: relative, damit wir den generierten Inhalt auf position: absolute setzen und relativ zum <span> positionieren können, anstatt zum <body> (Der generierte Inhalt verhält sich so, als wäre er ein Kindknoten des Elements, auf dem er generiert wird, für die Zwecke der Positionierung).

Dann geben wir dem generierten Inhalt den Inhalt "erforderlich", was es sagen soll. Wir gestalten und positionieren es nach unseren Wünschen. Das Ergebnis ist unten zu sehen (drücken Sie den Abspielen-Knopf, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten).

Gestaltung von Steuerelementen basierend darauf, ob ihre Daten gültig sind

Das andere wirklich wichtige, grundlegende Konzept bei der Formularvalidierung ist, ob die Daten einer Formulareingabe gültig sind oder nicht (bei numerischen Daten können wir auch von in-Bereich und außerhalb-Bereich sprechen). Formularelemente mit Einschränkungen bei der Validierung können basierend auf diesen Zuständen gezielt angesprochen werden.

:valid und :invalid

Sie können Formularelemente mit den Pseudoklassen :valid und :invalid gezielt ansprechen. Einige Punkte, die zu beachten sind:

  • Steuerelemente ohne Einschränkungen bei der Validierung sind immer gültig und daher mit :valid abgeglichen.
  • Steuerelemente mit required, die keinen Wert haben, werden als ungültig angesehen — sie werden mit :invalid und :required abgeglichen.
  • Steuerelemente mit integrierter Validierung, wie <input type="email"> oder <input type="url">, werden mit :invalid abgeglichen, wenn die in sie eingegebenen Daten nicht dem von ihnen gesuchten Muster entsprechen (aber sie sind gültig, wenn sie leer sind).
  • Steuerelemente, deren aktueller Wert außerhalb der durch die min und max Attribute festgelegten Bereichsgrenzen liegt, werden mit :invalid abgeglichen, aber auch durch :out-of-range, wie Sie später sehen werden.
  • Es gibt einige andere Möglichkeiten, ein Element mit :valid/:invalid abgleichen zu lassen, wie Sie im Client-seitige Formularvalidierung-Artikel sehen werden. Aber wir halten die Dinge vorerst einfach.

Lassen Sie uns ein Beispiel für :valid/:invalid ansehen.

Wie im vorherigen Beispiel haben wir zusätzliche <span>s, um darauf Inhalte zu generieren, die als Indikatoren für gültige oder ungültige Daten dienen:

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 die <span>s auf position: relative, damit wir den generierten Inhalt relativ zu ihnen positionieren können. Wir positionieren dann absolut unterschiedliche generierte Inhalte, je nachdem, ob die Formulardaten gültig oder ungültig sind — ein grüner Haken oder ein rotes Kreuz, jeweils. Um den ungültigen Daten etwas mehr Dringlichkeit zu verleihen, haben wir den Eingaben auch einen dicken roten Rand gegeben, wenn sie ungültig sind.

Hinweis: Wir haben ::before verwendet, um diese Labels hinzuzufügen, da wir ::after bereits für die "erforderlich"-Etiketten verwendet haben.

Sie können es unten ausprobieren (drücken Sie den Abspielen-Knopf, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):

Beachten Sie, wie die erforderlichen Texteingaben ungültig sind, wenn sie leer sind, aber gültig werden, wenn etwas eingetragen wird. Das E-Mail-Eingabefeld ist hingegen gültig, wenn es leer ist, da es nicht erforderlich ist, aber ungültig, wenn etwas enthalten ist, das keine richtige E-Mail-Adresse ist.

In-Bereich und Außerhalb-Bereich Daten

Wie oben angedeutet, gibt es zwei weitere verwandte Pseudoklassen zu berücksichtigen — :in-range und :out-of-range. Diese beziehen sich auf numerische Eingaben, bei denen Bereichsgrenzen durch die min und max Attribute festgelegt sind, wenn ihre Daten innerhalb oder außerhalb des angegebenen Bereichs liegen, jeweils.

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

Es ist wert zu erwähnen, dass Eingaben, deren Daten im Bereich liegen, auch durch die :valid-Pseudoklasse abgeglichen werden, und Eingaben, deren Daten außerhalb des Bereichs liegen, auch durch die :invalid-Pseudoklasse. Warum also beide haben? Die Frage ist eigentlich eine semantische — außerhalb des Bereiches ist eine spezifischere Art der ungültigen Kommunikation, sodass Sie möglicherweise eine andere Nachricht für außerhalb des Bereichs liegende Eingaben bereitstellen möchten, die hilfreicher für die Benutzer ist, als einfach nur "ungültig" zu sagen. Sie möchten möglicherweise sogar beides bereitstellen.

Schauen wir uns ein Beispiel an, das genau dies tut und auf dem vorherigen Beispiel aufbaut, um Nachrichten außerhalb des Bereichs für die numerischen Eingaben bereitzustellen, und auch angibt, ob sie 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 folgendermaßen 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 ist eine ähnliche Geschichte wie zuvor im :required Beispiel, außer dass wir hier die Deklarationen, die für irgendwelche ::after-Inhalte gelten, in eine separate Regel ausgelagert haben, und die separaten ::after-Inhalte für die Zustände :required und :out-of-range ihren eigenen Inhalt und Stil gegeben haben. Sie können es hier ausprobieren (drücken Sie den Abspielen-Knopf, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):

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

Das funktioniert ziemlich gut — wenn die Seite zum ersten Mal lädt, wird "Erforderlich" angezeigt, zusammen mit einem roten Kreuz und Rand. Wenn Sie ein gültiges Alter eingetippt haben (d.h. im Bereich von 12-120), wird die Eingabe gültig. Wenn Sie jedoch das Altersfeld entsprechend ändern, sodass es außerhalb des Bereichs liegt, dann blinkt die Meldung "Außerhalb des zulässigen Wertebereichs" auf, anstatt "Erforderlich".

Hinweis: Um einen ungültigen/Außer-Bereich-Wert einzugeben, müssen Sie das Formular tatsächlich fokussieren und es mit der Tastatur eintippen. Die Spin-Schaltflächen lassen Sie den Wert außerhalb des zulässigen Bereichs nicht inkrementieren/dekrementieren.

Gestaltung von aktivierten und deaktivierten Eingaben sowie schreibgeschützten und schreibbaren Eingaben

Ein aktiviertes Element ist ein Element, das aktiviert werden kann; es kann ausgewählt, angeklickt oder beschrieben werden. Ein deaktiviertes Element hingegen kann auf keine Weise interagiert werden und seine Daten werden nicht einmal an den Server gesendet.

Diese beiden Zustände können mit :enabled und :disabled gezielt werden. Warum sind deaktivierte Eingaben nützlich? Nun, manchmal, wenn einige Daten für einen bestimmten Benutzer nicht zutreffen, möchten Sie diese Daten möglicherweise nicht einmal senden, wenn sie das Formular senden. Ein klassisches Beispiel ist ein Versandformular — normalerweise werden Sie gefragt, ob Sie dieselbe Adresse für Rechnungsstellung und Versand verwenden möchten; wenn ja, können Sie einfach eine einzige Adresse an den Server senden und könnten genauso gut die Rechnungsadressenfelder deaktivieren.

Schauen wir uns ein Beispiel an, das genau dies tut. Zunächst ist das HTML ein einfaches Formular mit Texteingaben, plus einem Kontrollkästchen, um das Deaktivieren der Rechnungsadresse ein- und auszuschalten. Die Rechnungsadressfelder 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>

Nun zum CSS. Die relevantesten Teile dieses Beispiels sind wie folgt:

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

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

Wir haben die Eingaben, die deaktiviert werden sollen, direkt mit input[type="text"]:disabled angezielt, aber wir wollten auch die entsprechenden Textetiketten ausgrauen. Da die Labels direkt vor ihren Eingaben stehen, haben wir diese mit der Pseudoklasse :has ausgewählt.

Nun haben wir endlich ein JavaScript verwendet, um das Deaktivieren der Rechnungsadressfelder 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);

Es verwendet das change-Ereignis, um dem Benutzer zu ermöglichen, die Rechnungsfelder ein-/auszuschalten und die Gestaltung der zugehörigen Etiketten umzuschalten.

Sie können das Beispiel unten in Aktion sehen (drücken Sie den Abspielen-Knopf, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):

Schreibgeschützt und beschreibbar

Ähnlich wie :disabled und :enabled zielen die Pseudoklassen :read-only und :read-write auf zwei Zustände ab, zwischen denen Formulareingaben umschalten können. Wie bei deaktivierten Eingaben kann der Benutzer schreibgeschützte Eingaben nicht bearbeiten. Im Gegensatz zu deaktivierten Eingaben werden jedoch schreibgeschützte Eingabewerte an den Server gesendet. Schreibbar bedeutet, dass sie bearbeitet werden können — ihr Standardzustand.

Eine Eingabe wird mithilfe des readonly-Attributs auf schreibgeschützt gesetzt. Stellen Sie sich als Beispiel eine Bestätigungsseite vor, auf der der Entwickler die Details, die auf vorherigen Seiten ausgefüllt wurden, an diese Seite übermittelt hat, mit dem Ziel, dass der Benutzer sie an einem Ort überprüft, eventuelle abschließende Daten hinzufügt und dann die Bestellung durch Senden bestätigt. 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 Fragment des HTMLs lautet wie folgt — beachten Sie das readonly-Attribut:

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 die oberste Reihe von Formularelementen nicht bearbeitbar ist, jedoch werden die Werte beim Senden des Formulars übermittelt. Wir haben die Formularkontrollen mit den Pseudoklassen :read-only und :read-write wie folgt gestaltet:

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 wie folgt aus (drücken Sie den Abspielen-Knopf, um das Beispiel im 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.

Zustände von Radios und Checkboxen — ausgewählt, Standard, unbestimmt

Wie wir in früheren Artikeln des Moduls gesehen haben, können Optionsfelder und Kontrollkästchen ausgewählt oder nicht ausgewählt sein. Es gibt jedoch noch ein paar andere Zustände zu berücksichtigen:

  • :default: Passt auf Options-/Kontrollkästchen, die standardmäßig beim Laden der Seite ausgewählt sind (d.h. indem man das checked-Attribut auf ihnen setzt). Diese passen zur :default Pseudoklasse, selbst wenn der Benutzer sie abwählt.
  • :indeterminate: Wenn Options-/Kontrollkästchen weder aus- noch abgewählt sind, werden sie als unbestimmt betrachtet und passen zur :indeterminate Pseudoklasse. Mehr dazu im Folgenden.

:checked

Wenn ausgewählt, werden sie mit der :checked Pseudoklasse abgeglichen.

Die häufigste Verwendung davon ist, einen anderen Stil auf das Kontrollkästchen oder das Optionsfeld hinzuzufügen, wenn es geprüft ist, in Fällen, in denen Sie das Standardsystem-Design mit appearance: none; entfernt haben und die Stile selbst aufbauen möchten. Wir haben Beispiele dafür im vorherigen Artikel gesehen, als wir über Gestaltung von Kontrollkästchen und Optionsfeldern mit appearance gesprochen haben.

Als Zusammenfassung sieht der :checked-Code aus unserem Beispiel für gestaltete Radiobuttons so 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 es hier ausprobieren (drücken Sie den Abspielen-Knopf, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):

Grundsätzlich bauen wir das Styling für den "inneren Kreis" eines Optionsfelds mit dem ::before Pseudoelement auf, setzen jedoch ein scale(0) transform darauf. Dann verwenden wir einen transition, um den generierten Inhalt auf dem Label schön in den Vordergrund zu animieren, wenn das Radio ausgewählt/geprüft ist. Der Vorteil der Verwendung eines Transforms anstelle eines Übergangs von width/height besteht darin, dass Sie transform-origin verwenden können, um es aus der Mitte des Kreises wachsen zu lassen, anstatt es aus einer Ecke des Kreises wachsen zu lassen, und es gibt kein Springen, da keine Box-Modell-Eigenschaftswerte aktualisiert werden.

:default und :indeterminate

Wie oben erwähnt, passt die :default Pseudoklasse zu Options-/Kontrollkästchen, die standardmäßig beim Laden der Seite ausgewählt sind, selbst wenn sie abgewählt werden. Dies könnte nützlich sein, um einen Indikator zu einer Liste von Optionen hinzuzufügen, um den Benutzer daran zu erinnern, was die Standard- (oder Start-)Optionen waren, falls sie ihre Auswahl zurücksetzen möchten.

Außerdem werden die oben genannten Options-/Kontrollkästchen durch die :indeterminate Pseudoklasse abgeglichen, wenn sie sich in einem Zustand befinden, in dem sie weder aus- noch abgewählt sind. Aber was bedeutet das? Elemente, die unbestimmt sind, sind:

  • <input/radio> Eingaben, wenn alle in einer gleichnamigen Gruppe nicht ausgewählt sind
  • <input/checkbox> Eingaben, deren indeterminate Eigenschaft durch JavaScript auf true gesetzt ist
  • <progress> Elemente, die keinen Wert haben.

Dies ist nichts, was Sie wahrscheinlich sehr oft verwenden werden. Ein Anwendungsfall könnte ein Indikator sein, der den Benutzern mitteilt, dass sie wirklich ein Optionsfeld auswählen müssen, bevor sie weitermachen.

Schauen wir uns ein paar abgeänderte Versionen des vorherigen Beispiels an, die den Benutzer daran erinnern, was die Standardoption war, und die Labels der Optionsfelder im unbestimmten Zustand gestalten. Beide haben 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 :default-Beispiel haben wir das checked-Attribut auf das mittlere Radio-Button-Element hinzugefügt, sodass es standardmäßig beim Laden ausgewählt wird. Wir haben dies dann mit dem folgenden CSS gestaltet:

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;
}

Dies bietet ein kleines "Standard"-Etikett auf dem Element, das ursprünglich beim Laden der Seite ausgewählt war. Beachten Sie hier, dass wir den nachfolgenden Geschwisterkombinator (~) anstelle des nächsten Geschwisterkombinators (+) verwenden — wir müssen dies tun, da das <span> nicht direkt nach dem <input> im Quellcode kommt.

Sehen Sie das Live-Ergebnis unten (drücken Sie den Abspielen-Knopf, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):

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

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;
  }
}

Dies erzeugt ein lustiges kleines animiertes Outline auf den Optionsfeldern, das hoffentlich darauf hinweist, dass Sie eines davon auswählen müssen!

Sehen Sie das Live-Ergebnis unten (drücken Sie den Abspielen-Knopf, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):

Weitere Pseudoklassen

Es gibt eine Reihe weiterer interessanter Pseudoklassen, und wir haben hier nicht genug Platz, um sie alle im Detail zu behandeln. Lassen Sie uns über ein paar andere sprechen, die Sie sich ansehen sollten.

  • Die :focus-within Pseudoklasse passt zu einem Element, das den Fokus erhalten hat oder enthält ein Element, das den Fokus erhalten hat. Dies ist nützlich, wenn Sie möchten, dass ein ganzes Formular in irgendeiner Weise hervorgehoben wird, wenn ein Eingabefeld darin fokussiert ist.
  • Die :focus-visible Pseudoklasse passt zu fokussierten Elementen, die über eine Tastaturinteraktion den Fokus erhalten haben (anstatt durch Berührung oder Maus) — nützlich, wenn Sie einen anderen Stil für Tastaturfokus im Vergleich zu Mausfokus (oder anderen) anzeigen möchten.
  • Die :placeholder-shown Pseudoklasse passt zu <input> und <textarea> Elementen, deren Platzhalter angezeigt wird (d.h. die Inhalte des placeholder Attributs), weil der Wert des Elements leer ist.

Die folgenden sind ebenfalls interessant, aber bisher nicht gut in Browsern unterstützt:

  • Die :blank Pseudoklasse wählt leere Formularelemente aus. :empty passt ebenfalls zu Elementen, die keine Kinder haben, wie <input>, aber es ist allgemeiner — es passt auch zu anderen Leerelementen wie <br> und <hr>. :empty hat eine angemessene Browser-Unterstützung; die Spezifikation der :blank Pseudoklasse ist noch nicht fertiggestellt, sodass sie in keinem Browser unterstützt wird.
  • Die :user-invalid Pseudoklasse wird, wenn sie unterstützt wird, ähnlich wie :invalid sein, aber mit einer besseren Benutzererfahrung. Wenn der Wert gültig ist, wenn die Eingabe den Fokus erhält, kann das Element während der Benutzer die Daten eingibt, wenn der Wert vorübergehend ungültig ist, möglicherweise :invalid entsprechen, wird jedoch nur :user-invalid entsprechen, wenn das Element den Fokus verliert. Wenn der Wert ursprünglich ungültig war, entspricht er sowohl :invalid als auch :user-invalid für die gesamte Dauer des Fokus. In ähnlicher Weise wie :invalid wird es aufhören, :user-invalid zu entsprechen, wenn der Wert gültig wird.

Zusammenfassung

Damit ist unser Blick auf UI-Pseudoklassen, die sich auf Formulareingänge beziehen, abgeschlossen. Spielen Sie weiter mit ihnen und erstellen Sie einige lustige Formularstile! Als nächstes gehen wir zu etwas anderem über — Client-seitige Formularvalidierung.