Anpassung semantischer Komponenten

Webfunktionen: Container-Stilabfragen

Mit Stilabfragen (@container style()) können Sie kontextbezogene Varianten auslösen, ohne fest codieren zu müssen, was den jeweiligen Kontext erzeugt oder darauf reagiert. Dadurch wird die Kopplung des Designsystems reduziert und die Erweiterbarkeit und Komponentenkapselung verbessert.

Beispielsweise kann eine section.featured { --surface: featured }-Regel einen Kontext markieren und eine Landingpage kann standardmäßig über main { --surface: featured } darauf verweisen. Komponenten können dann auf --surface: featured reagieren: Auf einer Karte wird ein Werbebadge angezeigt, eine Schaltfläche wird standardmäßig in der ausgefüllten Variante angezeigt usw.

Mit Stilabfragen können beide Seiten entkoppelt bleiben: Die vorgestellten Oberflächen benennen nie die Elemente, die sich an sie anpassen, und die Komponenten prüfen nie, was den Kontext erzeugt hat. Beide Seiten können unabhängig voneinander erweitert werden – neue Komponenten, neue Oberflächen –, ohne die andere Seite zu berühren. Nachfolgerselektoren (z.B. .featured .button) erzwingen das Gegenteil: Der Selektor muss beide Seiten der Beziehung codieren und muss sich ändern, wenn sich eine der beiden Seiten ändert.

Wann Sie diesen Leitfaden verwenden sollten

In diesem Leitfaden geht es um Verhaltensänderungen: Eine Komponente entscheidet, was gerendert werden soll, wie sie sich anordnet oder welche Variante präsentiert werden soll, je nach Kontext. Das kann das Ausblenden oder Einblenden eines Badges, das Ändern der Layoutrichtung oder das Austauschen einer Schaltflächenvariante sein.

Wenn Sie stattdessen Änderungen auf Tokenebene benötigen, z. B. Dichtemodi, Designs oder andere übergeordnete Tokens, die Werte wie Abstände und Farben komponentenübergreifend einheitlich ändern, lesen Sie den Hilfeartikel Design Token Reactivity.

Das richtige Tool auswählen

Verwenden Sie eine Stilabfrage, wenn sich beide Seiten einer kontextuellen Beziehung unabhängig voneinander ändern können. Neue Elemente können den Kontext erzeugen oder neue Komponenten können darauf reagieren. Die Indirektion zahlt sich durch Erweiterbarkeit und Kapselung aus. Stilabfragen überschreiten Shadow-DOM-Grenzen, was mit Nachfahrenselektoren nicht möglich ist. Wenn diese Flexibilität nicht erforderlich ist, sollten Sie das einfachere Tool bevorzugen:

  • Nachfahrenselektoren (.toolbar .button): eine feste, einmalige Beziehung, die nicht wiederverwendbar oder erweiterbar ist. YAGNI gilt – fügen Sie keine indirekten Verweise hinzu, die Sie nicht verwenden werden.
  • Größenabfragen (@container (min-width: …)): Layout- und Dichteänderungen, die durch den verfügbaren Platz und nicht durch den semantischen Zustand bestimmt werden.
  • Stilabfragen (@container style(…)): Semantischer Zustand – was eine Komponente in einem bestimmten Kontext rendern, anordnen oder präsentieren soll.

Implementierungsanweisungen

  1. Definieren Sie ein semantisches Kontext-Flag mithilfe einer benutzerdefinierten CSS-Eigenschaft für einen Container.
  2. Legen Sie container-type NICHT für Stilabfragen fest. Sie fragen geerbte benutzerdefinierte Eigenschaften für das nächste übergeordnete Element ab und erfordern keinen expliziten Containment-Kontext.
  3. OBLIGATORISCH: Verwenden Sie @container style(--property: value), um bedingte Designs auf untergeordnete Elemente anzuwenden. Stilabfragen können nicht mit dem Element übereinstimmen, für das die Property festgelegt ist, sondern nur mit seinen Nachfolgern.
  4. DO prefer style queries over descendant selectors when the relationship must stay extensible or cross component/shadow DOM boundaries (see Choosing the right tool above) — but keep descendant selectors for fixed, one-off relationships where the indirection buys nothing.

Implementierungsbeispiel

/* 1. Set the context on a layout container */
.featured {
  --surface: featured; /* Semantic context flag for children */
}

/* 2. Component reacts to inherited flag */
.button {
  /* Default: Outlined informational style */
  background: transparent;
  border: 1px solid currentColor;
}

.badge {
  /* Default: Hidden — only revealed in featured surfaces */
  display: none;
}

@container style(--surface: featured) {
  .button {
    /* Automatic switch to Filled promotional style */
    background: var(--brand-accent);
    color: white;
    border: none;
  }

  .badge {
    /* Reveal decorative elements only in featured context */
    display: block;
  }
}

Fallback-Strategien

Bis Containerstilabfragen allgemein verfügbar sind, sollten Sie sie als progressive Verbesserung einsetzen: Stellen Sie einen selektorbasierten Standard bereit, der überall funktioniert, und lassen Sie ihn von der Stilabfrage überschreiben, wenn sie unterstützt wird. Verwenden Sie :where() für die Kontextauswahl, damit die Stilabfrage (gleiche Spezifität, später in der Quellreihenfolge) automatisch gewinnt.

/* Default styles — work everywhere */
.button {
  background: transparent;
  border: 1px solid currentColor;
}

.badge {
  display: none;
}

/* Selector-based contextual styles — broad browser support */
:where(.featured) .button {
  background: var(--brand-accent);
  color: white;
  border: none;
}

:where(.featured) .badge {
  display: block;
}

/* Progressive enhancement: style queries override when supported */
@container style(--surface: featured) {
  .button {
    background: var(--brand-accent);
    color: white;
    border: none;
  }

  .badge {
    display: block;
  }
}

Der Selector-Fallback verknüpft das kontextbezogene Styling mit einem Klassennamen, wodurch die Komponente mit ihrer DOM-Platzierung verbunden wird. Sobald Stilabfragen allgemein unterstützt werden, kann die :where()-Regel entfernt werden.