Benutzerdefinierte Zustands-Pseudo-Klassen in Chrome

Avatar of Šime Vidas
Šime Vidas am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Es gibt eine zunehmende Anzahl von „benutzerdefinierten“ Funktionen auf der Webplattform. Wir haben benutzerdefinierte Eigenschaften (--meine-eigenschaft), benutzerdefinierte Elemente (<mein-element>) und benutzerdefinierte Ereignisse (new CustomEvent('meinEreignis')). Irgendwann erhalten wir vielleicht sogar benutzerdefinierte Media Queries (@media (--meine-Medien)).

Aber das ist noch nicht alles! Möglicherweise haben Sie es verpasst, da es in Googles Artikel „Neu in Chrome 90“ nicht erwähnt wurde (um fair zu sein, declarative shadow DOM hat die Show in dieser Version gestohlen), aber Chrome hat gerade Unterstützung für eine weitere „benutzerdefinierte“ Funktion hinzugefügt: benutzerdefinierte Zustands-Pseudo-Klassen (:--mein-zustand).

Eingebaute Zustände

Bevor wir über benutzerdefinierte Zustände sprechen, werfen wir einen kurzen Blick auf die eingebauten Zustände, die für eingebaute HTML-Elemente definiert sind. Das CSS Selectors Modul und der Abschnitt „Pseudo-Klassen“ des HTML Standards definieren eine Reihe von Pseudo-Klassen, die verwendet werden können, um Elemente in verschiedenen Zuständen abzugleichen. Die folgenden Pseudo-Klassen werden heute in den Browsern weitgehend unterstützt

Benutzeraktion
:hover der Mauszeiger schwebt über dem Element
:active das Element wird vom Benutzer aktiviert
:focus das Element hat den Fokus
:focus-within das Element hat den Fokus oder enthält ihn
Position
:visited der Link wurde vom Benutzer besucht
:target das Element wird durch das Fragment der Seiten-URL adressiert
Eingabe
:disabled das Formularelement ist deaktiviert
:placeholder-shown das Eingabeelement zeigt Platzhaltertext an
:checked die Checkbox oder Radio-Schaltfläche ist ausgewählt
:invalid der Wert des Formularelements ist ungültig
:out-of-range der Wert des Eingabeelements ist außerhalb des angegebenen Bereichs
:-webkit-autofill das Eingabeelement wurde vom Browser automatisch ausgefüllt
Andere
:defined das benutzerdefinierte Element wurde registriert

Hinweis: Aus Gründen der Kürze wurden einige Pseudo-Klassen weggelassen und einige Beschreibungen erwähnen nicht alle möglichen Anwendungsfälle.

Benutzerdefinierte Zustände

Ähnlich wie eingebaute Elemente können benutzerdefinierte Elemente verschiedene Zustände haben. Eine Webseite, die ein benutzerdefiniertes Element verwendet, möchte diese Zustände möglicherweise stylen. Das benutzerdefinierte Element könnte seine Zustände über CSS-Klassen (class Attribut) auf seinem Host-Element verfügbar machen, aber das gilt als Anti-Pattern.

Chrome unterstützt jetzt eine API zum Hinzufügen interner Zustände zu benutzerdefinierten Elementen. Diese benutzerdefinierten Zustände werden über benutzerdefinierte Zustands-Pseudo-Klassen für die äußere Seite verfügbar gemacht. Zum Beispiel kann eine Seite, die ein <live-score> Element verwendet, Stile für den benutzerdefinierten --loading Zustand dieses Elements deklarieren.

live-score {
  /* default styles for this element */
}

live-score:--loading {
  /* styles for when new content is loading */
}

Fügen wir einem <labeled-checkbox>-Element einen --checked-Zustand hinzu

Die Spezifikation Custom State Pseudo Class enthält ein vollständiges Codebeispiel, das ich zur Erklärung der API verwenden werde. Der JavaScript-Teil dieser Funktion befindet sich in der Klassendefinition des benutzerdefinierten Elements. Im Konstruktor wird ein „Element-Internals“-Objekt für das benutzerdefinierte Element erstellt. Anschließend können benutzerdefinierte Zustände im internen states-Objekt gesetzt und aufgehoben werden.

Beachten Sie, dass die ElementInternals API sicherstellt, dass die benutzerdefinierten Zustände für die Außenwelt schreibgeschützt sind. Mit anderen Worten, die äußere Seite kann die internen Zustände des benutzerdefinierten Elements nicht ändern.

class LabeledCheckbox extends HTMLElement {
  constructor() {
    super();

    // 1. instantiate the element’s “internals”
    this._internals = this.attachInternals();

    // (other code)
  }

  // 2. toggle a custom state
  set checked(flag) {
    if (flag) {
      this._internals.states.add("--checked");
    } else {
      this._internals.states.delete("--checked");
    }
  }

  // (other code)
}

Die Webseite kann nun die internen Zustände des benutzerdefinierten Elements über benutzerdefinierte Pseudo-Klassen mit demselben Namen stylen. In unserem Beispiel wird der --checked-Zustand über die :--checked-Pseudo-Klasse verfügbar gemacht.

labeled-checkbox {
  /* styles for the default state */
}

labeled-checkbox:--checked {
  /* styles for the --checked state */
}
Probieren Sie die Demo in Chrome aus

Diese Funktion ist (noch) kein Standard

Browserhersteller diskutieren seit drei Jahren, wie die internen Zustände von benutzerdefinierten Elementen über benutzerdefinierte Pseudo-Klassen verfügbar gemacht werden können. Googles Custom State Pseudo Class Spezifikation bleibt ein „inoffizieller Entwurf“, der von WICG gehostet wird. Die Funktion hat eine Design-Überprüfung im W3C TAG durchlaufen und wurde an die CSS Working Group übergeben. In der Chrome-Diskussion „intent to ship“ schrieb Mounir Lamouri

Es scheint, dass diese Funktion eine gute Unterstützung hat. Es klingt, als ob es für Webentwickler schwierig sein könnte, davon zu profitieren, solange sie nicht weit verbreitet ist, aber hoffentlich werden Firefox und Safari folgen und sie ebenfalls implementieren. Jemand muss sie zuerst implementieren, und da es keine abwärtskompatiblen Änderungen absehbar sind, klingt es sicher, zuerst zu gehen.

Nun müssen wir auf die Implementierungen in Firefox und Safari warten. Die Browser-Bugs wurden eingereicht (Mozilla #1588763 und WebKit #215911), haben aber bisher wenig Aufmerksamkeit erhalten.