UI-Pseudo-Klassen

In den vorherigen Artikeln haben wir das Styling von verschiedenen Formularsteuerungen allgemein behandelt. Dazu gehörte auch die Verwendung von Pseudo-Klassen, zum Beispiel die Verwendung von :checked, um ein Kontrollkästchen nur anzusprechen, wenn es ausgewählt ist. In diesem Artikel erkunden wir die verschiedenen UI-Pseudo-Klassen, die zum Styling von Formularen in verschiedenen Zuständen verfügbar sind.

Voraussetzungen: Grundkenntnisse in HTML und CSS, einschließlich allgemeinem Wissen über Pseudo-Klassen und Pseudo-Elemente.
Ziel: Zu verstehen, welche Teile von Formularen schwer zu gestalten sind und warum; zu lernen, was getan werden kann, um sie anzupassen.

Welche Pseudo-Klassen stehen zur Verfügung?

Die ursprünglichen Pseudo-Klassen (aus CSS 2.1), die für Formulare relevant sind, sind:

  • :hover: Wählt ein Element nur aus, wenn es mit einem Mauszeiger darüber gefahren wird.
  • :focus: Wählt ein Element nur aus, wenn es fokussiert ist (d. h. durch das Navigieren mit der Tastatur).
  • :active: Wählt ein Element nur aus, während es aktiviert wird (d. h. während es angeklickt wird oder wenn im Fall einer Tastaturaktivierung die Taste Return / Enter gedrückt wird).

Diese grundlegenden Pseudo-Klassen sollten Ihnen inzwischen vertraut sein. CSS-Selektoren bieten mehrere andere Pseudo-Klassen, die sich auf HTML-Formulare beziehen. Diese bieten mehrere nützliche Zielbedingungen, die Sie nutzen können. Wir werden diese im Folgenden detaillierter besprechen, aber kurz zusammengefasst sind die wichtigsten, die wir uns ansehen werden:

  • :required und :optional: Zielgerichtete 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, sowie :in-range und :out-of-range: Zielgerichtete Formularsteuerelemente, die gültig oder ungültig gemäß den für sie festgelegten Formularvalidierungsbeschränkungen oder innerhalb der Reichweite oder außerhalb der Reichweite sind.
  • :enabled und :disabled, sowie :read-only und :read-write: Zielgerichtete Elemente, die deaktiviert werden können (z. B. Elemente, die das disabled HTML-Attribut unterstützen), je nachdem, ob sie derzeit aktiviert oder deaktiviert sind, und Lese-Schreib- oder Nur-Lese-Formularsteuerelemente (z. B. Elemente mit dem HTML-Attribut readonly versehen).
  • :checked, :indeterminate, und :default: Zielgerichtet auf Kontrollkästchen und Optionsfelder, die aktiviert sind, sich in einem unbestimmten Zustand befinden (weder aktiviert noch nicht aktiviert) und die standardmäßig ausgewählte Option beim Laden der Seite (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 die offensichtlich nützlichsten. Einige von ihnen richten sich an sehr spezifische Nischenprobleme. Die oben aufgeführten UI-Pseudo-Klassen 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 Pseudo-Klassen befassen sich mit dem Styling von Formularsteuerelementen basierend auf ihrem Validierungsstatus (Ist ihre Eingabe gültig oder nicht?). Sie werden viel mehr über das Festlegen und Kontrollieren von Validierungsbeschränkungen in unserem nächsten Artikel erfahren — Clientseitige Formularvalidierung — aber vorerst halten wir die Dinge in Bezug auf die Formularvalidierung einfach, um Verwirrung zu vermeiden.

Styling von Eingaben basierend darauf, ob sie erforderlich sind oder nicht

Eines der grundlegendsten Konzepte der clientseitigen Formularvalidierung ist, ob eine Formulareingabe erforderlich ist (sie muss ausgefüllt werden, bevor das Formular eingereicht werden kann) oder optional.

<input>, <select>, und <textarea>-Elemente haben ein verfügbares required Attribut, das, wenn gesetzt, bedeutet, dass Sie dieses Steuerelement ausfüllen müssen, bevor das Formular erfolgreich eingereicht wird. Zum Beispiel:

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 (include if you want a response):
      </label>
      <input id="email" name="email" type="email" />
    </div>
    <div><button>Submit</button></div>
  </fieldset>
</form>

Hier sind der Vorname und der Nachname erforderlich, aber die E-Mail-Adresse ist optional.

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

css
input:required {
  border: 1px solid black;
}

input:optional {
  border: 1px solid silver;
}

Hätten die erforderlichen Steuerelemente einen schwarzen Rand, und das optionale Steuerelement hätte einen silbernen Rand, wie unten gezeigt:

Sie können auch versuchen, das Formular abzusenden, ohne es auszufüllen, um die clientseitigen Validierungsfehlermeldungen zu sehen, die Ihnen die Browser standardmäßig anzeigen.

Das obige Formular ist nicht schlecht, aber es ist auch nicht großartig. Zum einen signalisieren wir erforderlichen gegen optionalen Status nur durch Farbe, was für farbenblinde Menschen nicht ideal ist. Zweitens ist die Standardkonvention im Web für erforderlichen Status ein Sternchen (*) oder das Wort "erforderlich", das mit den betreffenden Steuerelementen verbunden ist.

Im nächsten Abschnitt werden wir ein besseres Beispiel für die Anzeige erforderlicher Felder mithilfe von :required untersuchen, das auch auf die Verwendung von generiertem Inhalt eingeht.

Hinweis: Sie werden die :optional Pseudo-Klasse wahrscheinlich nicht sehr oft verwenden. Formularelemente sind standardmäßig optional, daher könnten Sie Ihr optionales Styling standardmäßig anwenden und Stile für erforderliche Steuerelemente darüber hinaus hinzufügen.

Hinweis: Wenn ein Optionsfeld in einer gleichnamigen Gruppe von Optionsfeldern das required Attribut gesetzt hat, sind alle Optionsfelder ungültig, bis eines ausgewählt wurde, aber nur das mit dem vergebenen Attribut wird tatsächlich mit :required abgeglichen.

Verwendung von generiertem Inhalt mit Pseudo-Klassen

In früheren Artikeln haben wir die Verwendung von generiertem Inhalt gesehen, aber wir dachten, jetzt wäre ein guter Zeitpunkt, um ein bisschen mehr darüber zu sprechen.

Die Idee ist, dass wir die Pseudo-Elemente ::before und ::after zusammen mit der content-Eigenschaft verwenden können, um ein Stück Inhalt vor oder nach dem betroffenen Element erscheinen zu lassen. Das Inhaltsstück wird nicht zum DOM hinzugefügt, sodass es für einige Screenreader unsichtbar sein kann. Da es sich um ein Pseudo-Element handelt, kann es auf die gleiche Weise mit Stilen angesprochen werden wie jedes tatsächliche DOM-Knoten.

Dies ist wirklich nützlich, wenn Sie einem Element, wie einem Etikett oder einem Symbol, einen visuellen Hinweis hinzufügen möchten, wenn alternative Indikatoren verfügbar sind, um die Zugänglichkeit für alle Benutzer sicherzustellen. Zum Beispiel verwenden wir in unserem beispielhaften benutzerdefinierten Optionsfeldern generierten Inhalt, um den Platz und die Animation des inneren Kreises eines benutzerdefinierten Optionsfelds zu handhaben, wenn ein Optionsfeld ausgewählt ist:

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, wenn ein Optionsfeld oder Kontrollkästchen, auf das sie treffen, aktiviert/ausgewählt ist. Daher möchten Sie nicht, dass sie ein weiteres DOM-Element vorlesen, das die Auswahl anzeigt — das könnte verwirrend sein. Ein rein visueller Indikator löst dieses Problem.

Nicht alle <input>-Typen unterstützen das Setzen von generiertem Inhalt auf ihnen. 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 Beispiel mit erforderlich/optional von vorher, diesmal werden wir das Erscheinungsbild der Eingabe selbst nicht ändern — wir werden generierten Inhalt verwenden, um ein hinweisendes Label hinzuzufügen (siehe es live hier und den Quellcode hier).

Zuerst fügen wir einen Absatz am Anfang des Formulars hinzu, um zu beschreiben, wonach Sie suchen:

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

Screenreader-Benutzer werden "erforderlich" als zusätzliche Information vorgelesen bekommen, wenn sie zu jeder erforderlichen Eingabe gelangen, während sehende Benutzer unser Label erhalten.

Wie bereits erwähnt, unterstützen Texteingaben keinen generierten Inhalt, daher fügen wir ein leeres <span> hinzu, an dem der generierte Inhalt aufgehängt wird:

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

Das unmittelbare Problem hierbei war, dass das Span auf eine neue Zeile unter der Eingabe fiel, da die Eingabe und das Etikett beide auf width: 100% gesetzt sind. Um dies zu beheben, gestalten wir das übergeordnete <div> als Flex-Container, der seine Inhalte auch auf neue Zeilen umbricht, wenn der Inhalt zu lang wird:

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

Der Effekt 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 derselben Zeile wie die Eingabe sitzen kann.

Nun zum generierten Inhalt. Wir erstellen es 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 diesen relativ zum <span> positionieren können, anstatt zum <body> (Der generierte Inhalt verhält sich, 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 wir wollten, dass unser Label sagt, und gestalten und positionieren es so, wie wir es wünschen. Das Ergebnis sehen Sie unten.

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

Das andere wirklich wichtige, grundlegende Konzept in der Formularvalidierung ist, ob die Daten eines Formularsteuerelements gültig sind oder nicht (im Fall von numerischen Daten können wir auch über innerhalb oder außerhalb des Bereichs sprechen). Formularsteuerelemente mit Einschränkungsbedingungen können basierend auf diesen Zuständen angesprochen werden.

:valid und :invalid

Sie können Formularsteuerelemente mit den Pseudo-Klassen :valid und :invalid ansprechen. Einige Punkte, die beachtet werden sollten:

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

Lassen Sie uns ein Beispiel für :valid/:invalid ansehen (siehe valid-invalid.html für die Live-Version, und überprüfen Sie auch den Quellcode).

Wie im vorherigen Beispiel haben wir zusätzliche <span>s, um darauf generierten Inhalt zu erzeugen, den wir verwenden, 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 die <span>s auf position: relative, sodass wir den generierten Inhalt relativ zu ihnen positionieren können. Wir positionieren dann absolut verschiedene generierte Inhalte, abhängig davon, ob die Daten des Formulars gültig oder ungültig sind — ein grüner Haken oder ein rotes Kreuz, entsprechend. Um ein wenig zusätzliche Dringlichkeit zu den ungültigen Daten zu geben, 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 bereits ::after für die "erforderlich" Labels verwendeten.

Sie können es unten ausprobieren:

Beachten Sie, wie die erforderlichen Texteingaben ungültig sind, wenn sie leer sind, aber gültig, wenn etwas ausgefüllt ist. Das E-Mail-Eingabefeld hingegen ist gültig, wenn es leer ist, da es nicht erforderlich ist, aber ungültig, wenn es etwas enthält, das keine richtige E-Mail-Adresse ist.

Daten innerhalb und außerhalb des Bereichs

Wie oben angedeutet, gibt es zwei andere verwandte Pseudo-Klassen zu berücksichtigen — :in-range und :out-of-range. Diese stimmen mit numerischen Eingaben überein, bei denen Bereichsgrenzen durch die Attribute min und max angegeben sind, wenn ihre Daten innerhalb oder außerhalb des angegebenen Bereichs liegen, entsprechend.

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

Es ist zu beachten, dass Eingaben, deren Daten im Bereich liegen, auch mit der :valid Pseudo-Klasse übereinstimmen und Eingaben, deren Daten außerhalb des Bereichs liegen, auch mit der :invalid Pseudo-Klasse übereinstimmen. Warum also beide haben? Es handelt sich hier wirklich um ein semantisches Problem — außerhalb des Bereichs ist eine spezifischere Art der ungültigen Kommunikation, sodass Sie möglicherweise eine andere Nachricht für außerhalb des Bereichs liegende Eingaben anzeigen möchten, die für die Benutzer hilfreicher sein wird als einfach "ungültig" zu sagen. Sie könnten sogar beide bereitstellen wollen.

Lassen Sie uns ein Beispiel ansehen, das genau dies tut. Unser out-of-range.html Demo (siehe auch den Quellcode) baut auf dem vorherigen Beispiel auf, um außerhalb des Bereichs liegende Nachrichten für die numerischen Eingaben bereitzustellen, sowie um anzuzeigen, ob sie erforderlich sind.

Die numerische Eingabe sieht so 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 ist eine ähnliche Geschichte wie wir es zuvor im :required Beispiel hatten, außer dass wir hier die Deklarationen, die auf jeden ::after Inhalt angewendet werden, in eine separate Regel aufgeteilt haben, und dem separaten ::after Inhalt für die :required und :out-of-range Zustände ihren eigenen Inhalt und Stilisierung gegeben haben. Sie können es hier ausprobieren:

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

Dies funktioniert ziemlich gut — wenn die Seite zum ersten Mal lädt, wird "Erforderlich" angezeigt, zusammen mit einem roten Kreuz und Rahmen. Wenn Sie jedoch ein gültiges Alter eingeben (d. h. im Bereich von 12 bis 120), wird die Eingabe gültig. Wenn Sie jedoch dann das Alter auf einen Wert ändern, der außerhalb des Bereichs liegt, wird die Nachricht "Außerhalb des zulässigen Wertebereichs" anstelle von "Erforderlich" angezeigt.

Hinweis: Um einen ungültigen/außerhalb des Bereichs liegenden Wert einzugeben, müssen Sie das Formular tatsächlich fokussieren und es über die Tastatur eingeben. Die Schaltflächen zum Erhöhen/Verringern lassen den Wert nicht außerhalb des zulässigen Bereichs.

Styling von aktivierten und deaktivierten Eingaben sowie Lese- und Schreibschutz

Ein aktiviertes Element ist ein Element, das aktiviert werden kann; es kann ausgewählt, angeklickt, eingetippt usw. werden. Ein deaktiviertes Element hingegen kann in keiner Weise interactied 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? Nun, manchmal, wenn einige Daten auf einen bestimmten Benutzer nicht zutreffen, möchten Sie diese Daten möglicherweise nicht einmal einreichen, wenn sie das Formular absenden. Ein klassisches Beispiel ist ein Versandformular — häufig 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 Rechnungsadressfelder deaktivieren.

Lassen Sie uns ein Beispiel ansehen, das genau dies tut. Zuerst einmal ist das HTML ein einfaches Formular, das Texteingaben enthält, plus ein Kontrollkästchen, um die Deaktivierung der Rechnungsadresse an- 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: #eee;
  border: 1px solid #ccc;
}

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

Wir haben die Eingaben, die wir deaktivieren möchten, direkt mit input[type="text"]:disabled ausgewählt, aber wir wollten auch die entsprechenden Textetiketten ausgrauen. Da sich die Etiketten direkt vor ihren Eingaben befinden, haben wir diese mit der Pseudo-Klasse :has ausgewählt.

Abschließend haben wir etwas JavaScript verwendet, um das Deaktivieren der Rechnungsadressfelder umzuschalten:

js
// Wait for the page to finish loading
document.addEventListener(
  "DOMContentLoaded",
  () => {
    // Attach `change` event listener to checkbox
    document
      .getElementById("billing-checkbox")
      .addEventListener("change", toggleBilling);
  },
  false,
);

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

  // Toggle the billing text fields
  for (let i = 0; i < billingItems.length; i++) {
    billingItems[i].disabled = !billingItems[i].disabled;
  }
}

Es verwendet das change event, um dem Benutzer zu ermöglichen, die Rechnungsfelder zu aktivieren/deaktivieren und das Styling der zugehörigen Bezeichnungen umschalten.

Sie können das Beispiel in Aktion unten sehen (auch sehen Sie es live hier, und sehen Sie den Quellcode):

Nur-Lese und Lese-Schreibschutz

In ähnlicher Weise wie :disabled und :enabled zielen die Pseudo-Klassen :read-only und :read-write auf zwei Zustände ab, zwischen denen Formulareingaben umschalten. Wie bei deaktivierten Eingaben kann der Benutzer keine Nur-Lese-Eingaben bearbeiten. Im Gegensatz zu deaktivierten Eingaben werden jedoch die Werte von Nur-Lese-Eingaben an den Server gesendet. Lese-Schreibschutz bedeutet, dass sie bearbeitet werden können — ihr Standardzustand.

Eine Eingabe wird mit dem Attribut readonly auf Nur-Lese gesetzt. Stellen Sie sich als Beispiel eine Bestätigungsseite vor, auf der der Entwickler die Details, die auf den vorherigen Seiten ausgefüllt wurden, auf diese Seite gesendet hat, mit dem Ziel, dass der Benutzer sie an einem Ort überprüft, alle erforderlichen Schlussinformationen hinzufügt und dann die Bestellung durch Absenden bestätigt. Zu diesem Zeitpunkt können alle endgültigen Formulardaten auf einmal an den Server gesendet werden.

Lassen Sie uns ansehen, wie ein Formular aussehen könnte (siehe readonly-confirmation.html für das Live-Beispiel; sehen Sie auch den Quellcode).

Ein Fragment des HTML sieht wie folgt 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, werden Sie sehen, dass die obere Reihe von Formularelementen nicht bearbeitbar ist, die Werte jedoch gesendet werden, wenn das Formular abgesendet wird. Wir haben die Formularelemente mit den Pseudo-Klassen :read-only und :read-write wie folgt formatiert:

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

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

Das vollständige Beispiel sieht so aus:

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

Radio- und Kontrollkästchenzustände — ausgewählt, Standard, unbestimmt

Wie wir in früheren Artikeln im Modul gesehen haben, können radio buttons und checkboxes ausgewählt oder nicht ausgewählt sein. Aber es gibt noch ein paar andere Zustände, die zu berücksichtigen sind:

  • :default: Entspricht Radios/Kontrollkästchen, die standardmäßig beim Laden der Seite aktiviert sind (d. h. durch Setzen des checked Attributs auf ihnen). Diese entsprechen der :default Pseudo-Klasse, selbst wenn der Benutzer sie abwählt.
  • :indeterminate: Wenn Radios/Kontrollkästchen weder ausgewählt noch abgewählt sind, werden sie als unbestimmt angesehen und entsprechen der :indeterminate Pseudo-Klasse. Mehr dazu unten.

:checked

Wenn sie ausgewählt sind, werden sie mit der :checked Pseudo-Klasse übereinstimmen.

Die häufigste Verwendung davon ist, einen anderen Stil auf das Kontrollkästchen oder das Optionsfeld anzuwenden, wenn es ausgewählt ist, in Fällen, in denen Sie das systemeigene Styling mit appearance: none; entfernt haben und die Stile selbst wieder aufbauen möchten. Wir haben Beispiele dafür im vorherigen Artikel gesehen, als wir die Verwendung von appearance: none auf Radios/Kontrollkästchen besprochen haben.

Als Rückblick sieht der :checked Code aus unserem Gestylte Optionsfelder Beispiel 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:

Im Grunde bauen wir das Styling für den "inneren Kreis" eines Optionsfelds mit dem ::before Pseudo-Element auf, setzen aber einen scale(0) transform darauf. Dann verwenden wir einen transition, um den generierten Inhalt auf dem Etikett schön in das Sichtfeld zu animieren, wenn das Radio ausgewählt/gecheckt ist. Der Vorteil der Verwendung einer Transformation anstelle der Transition von width/height besteht darin, dass Sie transform-origin verwenden können, um es aus der Mitte des Kreises wachsen zu lassen, anstatt aus der Ecke des Kreises zu erscheinen, und es gibt kein Springverhalten, da keine Boxmodell-Eigenschaftswerte aktualisiert werden.

:default und :indeterminate

Wie oben erwähnt, entspricht die :default Pseudo-Klasse Radios/Kontrollkästchen, die standardmäßig beim Laden der Seite aktiviert sind, selbst wenn sie abgewählt werden. Dies könnte nützlich sein, um einen Indikator zu einer Liste von Optionen hinzuzufügen, der den Benutzer daran erinnert, was die Standardeinstellungen (oder Anfangsoptionen) waren, falls sie ihre Entscheidungen zurücksetzen möchten.

Auch werden die oben erwähnten Radios/Kontrollkästchen mit der :indeterminate Pseudo-Klasse übereinstimmen, wenn sie sich in einem Zustand befinden, in dem sie weder ausgewählt noch nicht ausgewählt sind. Was bedeutet das? Elemente, die indeterminiert sind, umfassen:

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

Dies ist wahrscheinlich etwas, das Sie nicht sehr oft verwenden werden. Einer der Anwendungsfälle könnte ein Indikator sein, um den Benutzern zu sagen, dass sie wirklich ein Optionsfeld auswählen müssen, bevor sie weitermachen.

Lassen Sie uns ein paar modifizierte Versionen des vorherigen Beispiels ansehen, die den Benutzer daran erinnern, was die Standardoption war, und die Etiketten von Optionsfeldern beim indeterminierten Zustand stilisieren. 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 dem mittleren Eingabefeld des Optionsfeldes hinzugefügt, sodass es beim Laden standardmäßig ausgewählt wird. Wir stilisieren 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;
}

Dies liefert beim Standardmäßig ausgewählten Element eine kleine "Standard"-Beschriftung. Beachten Sie, dass wir hier den nachfolgenden Geschwister-Kombinator (~) anstelle des nächsten Geschwister-Kombinator (+) verwendet haben — wir müssen dies tun, da die <span> nicht direkt nach der <input> in der Quellreihenfolge kommt.

Sehen Sie das Live-Ergebnis unten:

Hinweis: Sie können das Beispiel auch live auf GitHub unter radios-checked-default.html (siehe auch den Quellcode) finden.

Für das :indeterminate Beispiel haben wir kein standardmäßig ausgewähltes Optionsfeld — das ist wichtig — wenn es eines gäbe, dann gäbe es keinen indeterminierten Zustand, den man stilisieren könnte. Wir gestalten die indeterminierten Optionsfelder mit dem folgenden 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;
  }
}

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

Sehen Sie das Live-Ergebnis unten:

Hinweis: Sie können das Beispiel auch live auf GitHub unter radios-checked-indeterminate.html (siehe auch den Quellcode) finden.

Hinweis: Auf der Seite der <input type="checkbox"> Referenzseite finden Sie ein interessantes Beispiel mit indeterminierte Zuständen.

Weitere Pseudo-Klassen

Es gibt eine Anzahl anderer interessanter Pseudo-Klassen, und wir haben nicht genug Platz, um sie alle hier im Detail zu behandeln. Lassen Sie uns über einige weitere sprechen, die Sie sich die Zeit nehmen sollten, sie zu untersuchen.

  • Die :focus-within Pseudo-Klasse entspricht einem Element, das den Fokus erhalten hat oder ein Element enthält, das den Fokus erhalten hat. Dies ist nützlich, wenn Sie ein gesamtes Formular in irgendeiner Weise hervorheben möchten, wenn ein darin enthaltenes Eingabefeld fokussiert ist.
  • Die :focus-visible Pseudo-Klasse entspricht fokussierten Elementen, die den Fokus über Tastaturinteraktion (und nicht über Berührung oder Maus) erhalten haben — nützlich, wenn Sie für Tastaturfokus einen anderen Stil zeigen möchten als für Maus- (oder anderen) Fokus.
  • Die :placeholder-shown Pseudo-Klasse entspricht <input> und <textarea>-Elementen, bei denen der Platzhalter angezeigt wird (d. h. der Inhalt des placeholder Attributs), weil der Wert des Elements leer ist.

Die folgenden sind auch interessant, aber noch nicht gut in Browsern unterstützt:

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

Testen Sie Ihre Fähigkeiten!

Sie haben das Ende dieses Artikels erreicht, aber können Sie sich noch an die wichtigsten Informationen erinnern? Sie können einige weitere Tests finden, um zu überprüfen, ob Sie diese Informationen behalten haben, bevor Sie fortfahren — siehe Testen Sie Ihre Fähigkeiten: Erweitertes Styling.

Zusammenfassung

Dies vervollständigt unseren Überblick über UI-Pseudo-Klassen, die sich auf Formulareingaben beziehen. Spielen Sie weiter mit ihnen und erstellen Sie einige lustige Formularstile! Als Nächstes widmen wir uns einem anderen Thema — Client-seitige Formularvalidierung.

Erweiterte Themen