UI-Pseudoklassen
In den vorherigen Artikeln haben wir das Styling verschiedener Formularsteuerelemente auf allgemeine Weise behandelt. Dies beinhaltete die Verwendung einiger Pseudoklassen, zum Beispiel das Verwenden von :checked
, um ein Kontrollkästchen nur dann zu markieren, wenn es ausgewählt ist. In diesem Artikel erkunden wir die verschiedenen verfügbaren UI-Pseudoklassen zum Stylen von Formularen in verschiedenen Zuständen.
Voraussetzungen: | Grundlegendes Verständnis von HTML und CSS, einschließlich allgemeiner Kenntnisse über Pseudoklassen und Pseudoelemente. |
---|---|
Ziel: | Zu verstehen, welche Teile von Formularen schwer zu stylen sind und warum; zu lernen, was getan werden kann, um sie anzupassen. |
Welche Pseudoklassen stehen zur Verfügung?
Möglicherweise sind Ihnen bereits die folgenden Pseudoklassen vertraut:
:hover
: Wählt ein Element nur aus, wenn es von einem Mauszeiger überfahren wird.:focus
: Wählt ein Element nur aus, wenn es fokussiert ist (d.h. wenn es über die Tastatur angesteuert wird).:active
: Wählt ein Element nur aus, wenn es aktiviert wird (d.h. während es angeklickt wird, oder wenn die Return- oder Enter-Taste bei einer Tastaturaktivierung gedrückt wird).
CSS-Selektoren bieten mehrere andere Pseudoklassen, die sich auf HTML-Formulare beziehen. Diese bieten einige nützliche Zielbedingungen, die Sie nutzen können. Wir werden diese im Detail in den untenstehenden Abschnitten besprechen, aber kurz gesagt, die Hauptpunkte, die wir betrachten werden, sind:
:required
und:optional
: Ziel sind Elemente, die erforderlich sein können (z. B. Elemente, die dasrequired
HTML-Attribut unterstützen), basierend darauf, ob sie erforderlich oder optional sind.:valid
und:invalid
, sowie:in-range
und:out-of-range
: Ziel sind Formularsteuerelemente, die gemäß den festgelegten Validierungsbeschränkungen gültig/ungültig oder im Bereich/außerhalb des Bereichs sind.:enabled
und:disabled
, sowie:read-only
und:read-write
: Ziel sind Elemente, die deaktiviert sein können (z. B. Elemente, die dasdisabled
HTML-Attribut unterstützen), basierend darauf, ob sie derzeit aktiviert oder deaktiviert sind, sowie Schreib- und Leseattribute (z. B. Elemente mit dem HTML-Attributreadonly
).:checked
,:indeterminate
und:default
: Respektive Ziel sind Checkboxen und Optionsfelder, die markiert sind, sich in einem unbestimmten Zustand befinden (weder markiert noch nicht markiert) und die standardmäßig ausgewählte Option, wenn die Seite geladen wird (z. B. ein<input type="checkbox">
mit demchecked
-Attribut oder ein<option>
-Element mit demselected
-Attribut).
Es gibt viele andere, aber die oben genannten sind die offensichtlich nützlichsten. Einige sind darauf ausgelegt, sehr spezifische Nischenprobleme zu lösen. Die oben aufgeführten UI-Pseudoklassen haben eine ausgezeichnete 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 dem Styling von Formularsteuerelementen basierend auf ihrem Validierungsstatus (ist ihre Eingabe gültig oder nicht?). Sie werden viel mehr darüber erfahren, wie Sie Validierungsbeschränkungen festlegen und steuern können, in unserem nächsten Artikel — Client-seitige Formularvalidierung — aber jetzt werden wir die Formularvalidierung einfach halten, damit es nicht zu Verwirrung führt.
Stileingaben basierend darauf, ob sie erforderlich sind oder nicht
Eines der grundlegendsten Konzepte im Zusammenhang mit der clientseitigen Formularvalidierung ist, ob eine Formulareingabe erforderlich ist (sie muss ausgefüllt werden, bevor das Formular eingereicht werden kann) oder optional ist.
<input>
, <select>
, und <textarea>
Elemente haben ein required
-Attribut, das, wenn es gesetzt ist, bedeutet, dass Sie dieses Steuerelement ausfüllen müssen, damit das Formular erfolgreich eingereicht werden kann.
Zum Beispiel sind der Vorname und der Nachname im untenstehenden Formular erforderlich, aber die E-Mail-Adresse ist optional:
<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 mithilfe der Pseudoklassen :required
und :optional
abgleichen. Beispielsweise, wenn wir das folgende CSS auf das obige HTML anwenden:
input:required {
border: 2px solid;
}
input:optional {
border: 2px dashed;
}
Die erforderlichen Steuerelemente haben einen durchgehenden Rahmen, und das optionale Steuerelement hat einen gestrichelten Rahmen. Sie können auch versuchen, das Formular einzureichen, ohne es auszufüllen, um die standardmäßigen clientseitigen Validierungsfehlermeldungen Ihrer Browser zu sehen:
Im Allgemeinen sollten Sie vermeiden, "erforderliche" gegenüber "optionalen" Elementen in Formularen nur mit Farbe zu stylen, da dies nicht ideal für Farbblinde ist:
input:required {
border: 2px solid red;
}
input:optional {
border: 2px solid green;
}
Der Standard auf dem Web zur Kennzeichnung ist ein Asterisk (*
) oder das Wort "erforderlich" in Zusammenhang mit den betreffenden Steuerelementen.
Im nächsten Abschnitt werden wir uns ein besseres Beispiel zur Kennzeichnung erforderlicher Felder mithilfe von :required
und generierten Inhalten ansehen.
Hinweis:
Sie werden wahrscheinlich feststellen, dass Sie die :optional
Pseudoklasse nicht oft nutzen werden. Formularelemente sind standardmäßig optional, sodass Sie Ihr optionales Styling standardmäßig vornehmen könnten und zusätzliche Styles für erforderliche Steuerelemente hinzufügen.
Hinweis:
Wenn ein Radio-Button in einer gleichnamigen Gruppe von Radio-Buttons das required
-Attribut hat, sind alle Radio-Buttons ungültig, bis einer ausgewählt ist, aber nur derjenige mit dem Attribut wird tatsächlich mit :required
abgeglichen.
Generierte Inhaltselemente mit Pseudoklassen verwenden
In vorherigen Artikeln haben wir die Verwendung von generierten Inhalten gesehen, aber wir dachten, jetzt wäre ein guter Zeitpunkt, darüber ausführlicher zu sprechen.
Die Idee ist, dass wir die Pseudoelemente ::before
und ::after
zusammen mit der content
Eigenschaft nutzen können, um ein Stück Inhalt zu erzeugen, der vor oder nach dem betroffenen Element erscheint. Der erzeugte Inhalt wird nicht zum DOM hinzugefügt, sodass er für einige Screenreader möglicherweise unsichtbar ist. Da es sich um ein Pseudoelement handelt, kann es mit Styles genauso behandelt werden wie ein tatsächlicher DOM-Knoten.
Dies ist besonders nützlich, wenn Sie einem Element, wie einem Label oder Icon, einen visuellen Indikator hinzufügen möchten, wenn alternative Indikatoren für alle Benutzer zugänglich sind. Beispielsweise können wir generierte Inhalte verwenden, um die Platzierung und Animation des inneren Kreises des benutzerdefinierten Radio-Buttons zu steuern, wenn ein Radio-Button ausgewählt ist:
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 besonders nützlich — Screenreader lassen ihre Benutzer bereits wissen, wenn ein Radio-Button oder Kontrollkästchen ausgewählt/markiert ist, also möchten Sie nicht, dass sie ein weiteres DOM-Element lesen, das die Auswahl anzeigt — das könnte verwirrend sein. Ein rein visueller Indikator löst dieses Problem.
Nicht alle <input>
-Typen unterstützen das Hinzufügen von generierten Inhalten. Alle Eingabetypen, die dynamischen Text anzeigen, wie text
, password
oder button
, zeigen keine generierten Inhalte an. Andere, wie range
, color
, checkbox
, usw., zeigen generierte Inhalte an.
Zurück zu unserem vorherigen Beispiel der erforderlichen/optionalen Felder, diesmal werden wir das Erscheinungsbild des Inputs selbst nicht verändern — wir verwenden generierte Inhalte, um ein Label hinzuzufügen.
Zuerst fügen wir oben in das Formular einen Absatz hinzu, um zu sagen, was Sie suchen:
<p>Required fields are labeled with "required".</p>
Screenreader-Benutzer erhalten "erforderlich" als zusätzliche Information, wenn sie zu jedem erforderlichen Eingabefeld gelangen, während sehende Benutzer unser Label sehen.
Wie bereits erwähnt, unterstützen Texteingaben keine generierten Inhalte, also fügen wir ein leeres <span>
hinzu, um den generierten Inhalt anzuhängen:
<div>
<label for="fname">First name: </label>
<input id="fname" name="fname" type="text" required />
<span></span>
</div>
Das unmittelbare Problem war, dass das span aufgrund des width: 100%
-Styles der Eingabe und des Labels auf eine neue Zeile fiel. Um dies zu beheben, stylen wir das übergeordnete <div>
als Flexcontainer und sagen ihm, seinen Inhalt auf neue Zeilen zu verschieben, wenn der Inhalt zu lang wird:
fieldset > div {
margin-bottom: 20px;
display: flex;
flex-flow: row wrap;
}
Der Effekt ist, dass sich das Label und die Eingabe auf separaten Zeilen befinden, da beide width: 100%
haben, aber das <span>
hat eine Breite von 0
, sodass es auf derselben Zeile wie die Eingabe stehen kann.
Jetzt zum generierten Inhalt. Wir erstellen ihn mit diesem 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 statt relativ zum <body>
(Der generierte Inhalt verhält sich, als ob er ein Knoten innerhalb des Elements ist, auf dem er generiert wurde, zwecks Positionierung).
Dann geben wir dem generierten Inhalt den Inhalt "erforderlich", was wir als unser Label sagen wollten, und stylen und positionieren es, wie wir möchten. Das Ergebnis ist unten zu sehen (drücken Sie den Play-Button, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten).
Stylen von Steuerelementen basierend darauf, ob ihre Daten gültig sind
Das andere wirklich wichtige, grundlegende Konzept im Bereich der Formularvalidierung ist, ob die Daten eines Formularelements gültig sind oder nicht (im Fall von numerischen Daten können wir auch über Daten innerhalb des Bereichs und außerhalb des Bereichs sprechen). Formularelemente mit Einschränkungen können basierend auf diesen Zuständen gezielt werden.
:valid und :invalid
Sie können Formularelemente mithilfe der Pseudoklassen :valid
und :invalid
ansprechen. Einige Überlegungen, die beachtet werden sollten:
- Elemente ohne Einschränkungsvalidierung sind immer gültig und werden daher mit
:valid
abgeglichen. - Elemente mit
required
, die keinen Wert haben, werden als ungültig gezählt — sie werden mit:invalid
und:required
abgeglichen. - Elemente mit eingebauter Validierung, z.B.
<input type="email">
oder<input type="url">
, werden (mit):invalid
übereingestimmt, wenn die eingegebenen Daten nicht dem Muster entsprechen, das sie suchen (aber sie sind gültig, wenn sie leer sind). - Elemente, deren aktueller Wert außerhalb der durch die Attribute
min
undmax
festgelegten Bereichsgrenzen liegt, werden (mit):invalid
übereingestimmt, aber auch mit:out-of-range
, wie Sie später sehen werden. - Es gibt noch andere Möglichkeiten, ein Element mit
:valid
/:invalid
übereinzustimmen, wie Sie im Artikel über die Client-seitige Formularvalidierung sehen werden. Aber wir halten die Dinge vorerst einfach.
Lassen Sie uns ein Beispiel für :valid
/:invalid
betrachten.
Wie im vorherigen Beispiel haben wir zusätzliche <span>
-Elemente, um Inhalte zu generieren, die wir verwenden werden, um Indikatoren für gültige oder ungültige Daten bereitzustellen:
<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:
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 bereits beschrieben, setzen wir die <span>
auf position: relative
, damit wir den generierten Inhalt relativ zu ihnen positionieren können. Wir positionieren dann unterschiedlichen generierten Inhalt, je nachdem, ob die Daten des Formulars gültig oder ungültig sind — ein grüner Haken oder ein rotes Kreuz, jeweils. Um ein wenig Dringlichkeit für die ungültigen Daten zu erzeugen, 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 verwendet haben.
Sie können es unten ausprobieren (drücken Sie den Play-Button, 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, wenn sie ausgefüllt sind. 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 gültige E-Mail-Adresse ist.
Daten im und außerhalb des Bereichs
Wie wir oben angedeutet haben, gibt es zwei weitere verwandte Pseudoklassen 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, jeweils.
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 Pseudoklasse :valid
übereinstimmen und Eingaben, deren Daten außerhalb des Bereichs liegen, auch mit :invalid
übereinstimmen. Warum haben wir dann beide? Das Problem ist wirklich eines der Semantik — "out-of-range" ist eine spezifischere Art der Invalid-Kommunikation, sodass Sie unter Umständen eine andere Nachricht für Eingaben außerhalb des Bereichs bereitstellen möchten, die hilfreicher für Benutzer ist als nur "ungültig" zu sagen. Sie könnten sogar beides bereitstellen.
Lassen Sie uns ein Beispiel betrachten, das genau dies tut und auf dem vorherigen Beispiel aufbaut, um Nachrichten außerhalb des Bereichs für numerische Eingaben bereitzustellen, sowie anzugeben, ob sie erforderlich sind.
Die numerische Eingabe sieht folgendermaßen aus:
<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:
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 sie vorher im :required
-Beispiel hatten, außer dass wir hier die Deklarationen, die auf allen ::after
-Inhalt angewendet werden, in eine separate Regel unterteilt haben und dem separaten ::after
-Inhalt für :required
und :out-of-range
ihren eigenen Inhalt und Stil gegeben haben. Sie können es hier ausprobieren (drücken Sie den Play-Button, 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. Was passiert dann? Da die :out-of-range
-Regel später im Quellcode erscheint als die :required
-Regel, greifen die Kaskadenregeln, und die Nachricht außerhalb des Bereichs wird angezeigt.
Das funktioniert ganz gut — wenn die Seite erstmals geladen wird, wird "Erforderlich" zusammen mit einem roten Kreuz und Rand angezeigt. Wenn Sie jedoch ein gültiges Alter eingegeben haben (d.h. im Bereich von 12-120), wird die Eingabe gültig. Wenn Sie hingegen die Altersangabe in eine ändern, die außerhalb des Bereichs liegt, erscheint die Nachricht "Außerhalb des zulässigen Wertebereichs" anstelle von "Erforderlich".
Hinweis: Um einen ungültigen/außerhalb des Bereichs liegenden Wert einzugeben, müssen Sie tatsächlich das Formular fokussieren und ihn mit der Tastatur eingeben. Die Spinner-Buttons lassen Sie den Wert außerhalb des zulässigen Bereichs nicht erhöhen/verringern.
Styling aktivierter und deaktivierter Eingaben sowie Schreib- und Leseattribute
Ein aktiviertes Element ist ein Element, das aktiviert werden kann; es kann ausgewählt, angeklickt, in es kann getippt werden usw. Ein deaktiviertes Element hingegen kann 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
abgestimmt werden. Warum sind deaktivierte Eingaben nützlich? Nun, manchmal, wenn bestimmte Daten für einen bestimmten Benutzer nicht gelten, möchten Sie diese Daten möglicherweise nicht einmal senden, wenn sie das Formular einreichen. Ein klassisches Beispiel ist ein Versandformular — oft wird gefragt, ob dieselbe Adresse für Rechnungsstellung und Versand verwendet werden soll; 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 anschauen, das genau dies tut. Zunächst einmal ist das HTML ein einfaches Formular mit Texteingaben und einem Kontrollkästchen, um das Deaktivieren der Rechnungsadresse ein- und auszuschalten. Die Rechnungsadressfelder sind standardmäßig deaktiviert.
<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 die folgenden:
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 sich die Labels direkt vor ihren Eingaben befinden, haben wir diese mit der Pseudoklasse :has
ausgewählt.
Nun schließlich verwenden wir etwas JavaScript, um das Deaktivieren der Rechnungsadressfelder umzuschalten:
// Attach `change` event listener to checkbox
document
.getElementById("billing-checkbox")
.addEventListener("change", toggleBilling);
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;
}
}
Es verwendet das change
-Ereignis, um dem Benutzer zu ermöglichen, die Rechnungungsfelder zu aktivieren/deaktivieren, und die Gestaltung der zugehörigen Labels umzuschalten.
Sie können das Beispiel unten in Aktion sehen (drücken Sie den Play-Button, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):
body {
font-family: "Josefin Sans", sans-serif;
margin: 20px auto;
max-width: 460px;
}
fieldset {
padding: 10px 30px 0;
margin-bottom: 20px;
}
legend {
color: white;
background: black;
padding: 5px 10px;
}
fieldset > div {
margin-bottom: 20px;
display: flex;
}
button,
label,
input[type="text"] {
display: block;
font-family: inherit;
font-size: 100%;
margin: 0;
box-sizing: border-box;
width: 100%;
padding: 5px;
height: 30px;
}
input {
box-shadow: inset 1px 1px 3px #cccccc;
border-radius: 5px;
}
input:hover,
input:focus {
background-color: #eeeeee;
}
input[type="text"]:disabled {
background: #eeeeee;
border: 1px solid #cccccc;
}
label:has(+ :disabled) {
color: #aaaaaa;
}
button {
width: 60%;
margin: 0 auto;
}
Schreibgeschützt und beschreibbar
In ähnlicher Weise wie :disabled
und :enabled
adressieren die Pseudoklassen :read-only
und :read-write
zwei Zustände, zwischen denen Formulareingaben wechseln können. Wie bei deaktivierten Eingaben kann der Benutzer schreibgeschützte Eingaben nicht bearbeiten. Allerdings werden im Gegensatz zu deaktivierten Eingaben schreibgeschützte Eingabewerte beim Einreichen an den Server übermittelt. Schreibbar bedeutet, dass sie bearbeitet werden können — ihr Standardzustand.
Ein Eingabefeld wird mit dem readonly
-Attribut auf schreibgeschützt gesetzt. Ein Beispiel: Stellen Sie sich eine Bestätigungsseite vor, auf der der Entwickler die auf den vorherigen Seiten ausgefüllten Daten an diese Seite gesendet hat, mit dem Ziel, dass der Benutzer sie an einem Ort überprüft, alle notwendigen letzten Daten hinzufügt und dann die Bestellung durch Einreichen bestätigt. An diesem Punkt können alle endgültigen Formulardaten in einem Durchgang an den Server gesendet werden.
Sehen wir uns an, wie ein Formular aussehen könnte.
Ein Fragment des HTML sieht wie folgt aus — beachten Sie das readonly-Attribut:
<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 Gruppe von Formularelementen nicht bearbeitet werden kann, jedoch werden die Werte beim Einreichen des Formulars übermittelt. Wir haben die Formulareingaben mit den Pseudoklassen :read-only
und :read-write
gestaltet, wie folgt:
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 den Play-Button, 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 Eingabefeldern beschreiben.
Radio- und Kontrollkästchenzustände — geprüft, Standard, unbestimmt
Wie wir in früheren Artikeln im Modul gesehen haben, können Radio-Buttons und Kontrollkästchen überprüft oder nicht überprüft sein. Aber es gibt noch ein paar andere Zustände zu berücksichtigen:
:default
: Kombiniert Radios/Kontrollkästchen, die standardmäßig beim Laden der Seite markiert sind (d.h. indem daschecked
-Attribut auf sie gesetzt wird). Diese stimmen dann mit der:default
-Pseudoklasse überein, auch wenn der Benutzer sie entfernt.:indeterminate
: Wenn Radios/Kontrollkästchen weder überprüft noch nicht überprüft sind, gelten sie als unbestimmt und stimmen mit der:indeterminate
-Pseudoklasse überein. Mehr dazu später.
:checked
Wenn sie überprüft sind, werden sie mit der :checked
-Pseudoklasse abgestimmt.
Der häufigste Anwendungsfall hierfür ist es, einen anderen Stil auf das Kontrollkästchen oder den Radio-Button anzuwenden, wenn es überprüft ist, in Fällen, in denen Sie das Standardsystemstyling mit appearance: none;
entfernt haben und die Styles selbst neu aufbauen möchten. Wir haben Beispiele dafür im vorherigen Artikel gesehen, als wir über Verwendung von appearance: none
bei Radios/Kontrollkästchen gesprochen haben.
Als Rückblick sieht der :checked
-Code aus unserem Beispiel der gestylten Radio-Buttons folgendermaßen aus:
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 Play-Button, 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 Radio-Buttons mithilfe des ::before
-Pseudoelements auf, setzen jedoch eine scale(0)
transform
darauf. Wir verwenden dann eine transition
, um den generierten Inhalt auf dem Label sanft in das Sichtfeld zu animieren, wenn das Radio ausgewählt/aktiviert ist. Der Vorteil der Verwendung einer Transformation anstelle der Transition von width
/height
besteht darin, dass Sie den transform-origin
verwenden können, um ihn vom Zentrum des Kreises wachsen zu lassen, anstatt von der Ecke des Kreises, und es gibt kein Sprungverhalten, da keine Boxmodell-Eigenschaftswerte aktualisiert werden.
:default und :indeterminate
Wie oben erwähnt, stimmt die :default
-Pseudoklasse mit Radios/Kontrollkästchen überein, die standardmäßig beim Laden der Seite überprüft sind, selbst wenn sie abgewählt sind. Dies könnte nützlich sein, um einen Indikator zu einer Liste von Optionen hinzuzufügen, um den Benutzer daran zu erinnern, was die Standardeinstellungen (oder Startoptionen) waren, falls sie ihre Auswahl zurücksetzen möchten.
Auch die oben genannten Radios/Kontrollkästchen werden als unbestimmt betrachtet, wenn sie in einem Zustand sind, in dem sie weder überprüft noch nicht überprüft sind, und mit der :indeterminate
-Pseudoklasse übereinstimmen. Aber was bedeutet das? Elemente, die unbestimmt sind, umfassen:
<input/radio>
-Eingaben, wenn alle Radio-Buttons in einer gleichnamigen Gruppe nicht überprüft sind<input/checkbox>
-Eingaben, derenindeterminate
-Eigenschaft über JavaScript auftrue
gesetzt ist<progress>
-Elemente, die keinen Wert haben.
Dies ist wahrscheinlich nicht etwas, das Sie sehr oft verwenden werden. Ein Anwendungsfall könnte ein Indikator sein, der den Benutzern sagt, dass sie wirklich einen Radio-Button auswählen müssen, bevor sie weitermachen.
Schauen wir uns ein paar modifizierte Versionen des vorherigen Beispiels an, die den Benutzer daran erinnern, welche Option die Standardoption war, und die Labels von Radio-Buttons im unbestimmten Zustand stylen. Beide haben die folgende HTML-Struktur für die Eingaben:
<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 zum mittleren Radio-Button-Input hinzugefügt, sodass er standardmäßig beim Laden ausgewählt wird. Wir stylen dies mit folgendem 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"-Label auf dem Element, das ursprünglich ausgewählt war, als die Seite geladen wurde. Beachten Sie hier, dass wir den Subsequent-Sibling-Kombinator (~
) anstelle des Next-Sibling-Kombinators (+
) verwenden — wir müssen das tun, weil das <span>
nicht direkt nach dem <input>
in der Quellreihenfolge kommt.
Sehen Sie das Live-Ergebnis unten (drücken Sie den Play-Button, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):
Für das :indeterminate
-Beispiel haben wir keinen standardmäßig ausgewählten Radio-Button — das ist wichtig — wenn es einen gäbe, gäbe es keinen unbestimmten Zustand, den man stylen kann. Wir stylen die unbestimmten Radio-Buttons mit folgendem 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 eine kleine animierte Umrandung auf den Radio-Buttons, die hoffentlich anzeigt, dass Sie einen von ihnen auswählen müssen!
Sehen Sie das Live-Ergebnis unten (drücken Sie den Play-Button, um das Beispiel im MDN Playground auszuführen und den Quellcode zu bearbeiten):
Hinweis:
Sie können ein interessantes Beispiel zu indeterminate
-Zuständen auf der Referenzseite zu <input type="checkbox">
finden.
Weitere Pseudoklassen
Es gibt eine Reihe von weiteren interessanten Pseudoklassen, und wir haben nicht den Platz, um sie alle im Detail zu erläutern. Lassen Sie uns über einige weitere sprechen, denen Sie Aufmerksamkeit schenken sollten.
- Die
:focus-within
-Pseudoklasse stimmt mit einem Element überein, das den Fokus erhalten hat oder ein Element enthält, das den Fokus erhalten hat. Dies ist nützlich, wenn Sie möchten, dass ein gesamtes Formular in irgendeiner Weise hervorgehoben wird, wenn ein darin befindliches Steuerelement fokussiert wird. - Die
:focus-visible
-Pseudoklasse stimmt mit fokussierten Elementen überein, die den Fokus per Tastaturinteraktion (anstelle von Touch oder Maus) erhalten haben — nützlich, wenn Sie einen anderen Stil für den Tastaturfokus im Vergleich zum Maus- (oder anderen) Fokus anzeigen möchten. - Die
:placeholder-shown
-Pseudoklasse stimmt mit<input>
und<textarea>
-Elementen überein, bei denen der Platzhalter angezeigt wird (d.h. der Inhalt desplaceholder
-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
stimmt auch mit Elementen überein, die keine Kinder haben, wie<input>
, aber es ist genereller — es passt auch auf andere leere Elemente wie<br>
und<hr>
.:empty
hat eine angemessene Browser-Unterstützung; die:blank
-Pseudoklasse wird noch spezifiziert und ist noch in keinem Browser unterstützt. - Die
:user-invalid
-Pseudoklasse wird, wenn sie unterstützt wird, ähnlich:invalid
sein, jedoch mit besserer Benutzererfahrung. Wenn der Wert gültig ist, wenn das Eingabefeld den Fokus erhält, kann das Element mit:invalid
übereinstimmen, während der Benutzer Daten eingibt, wenn der Wert vorübergehend ungültig ist, aber es wird nur mit:user-invalid
übereinstimmen, wenn das Element den Fokus verliert. Wenn der Wert ursprünglich ungültig war, stimmt es sowohl mit:invalid
als auch mit:user-invalid
überein, während des gesamten Fokus. In ähnlicher Weise wie:invalid
wird es aufhören, mit:user-invalid
übereinzustimmen, wenn der Wert tatsächlich gültig wird.
Zusammenfassung
Damit ist unser Blick auf UI-Pseudoklassen abgeschlossen, die mit Formulareingaben zusammenhängen. Spielen Sie weiter mit ihnen und kreieren Sie einige unterhaltsame Formulare! Als Nächstes werden wir uns einem anderen Thema zuwenden — client-seitige Formularvalidierung.