:is() und :where() – kürzere Selektoren, und einer davon wiegt nichts
Drei fast gleiche Selektoren untereinander, nur weil die Überschrift mal h2 und mal h3 heißt? :is() fasst das zusammen. Und :where() macht dasselbe, ohne die Spezifität hochzutreiben – der Unterschied ist der ganze Trick.
Wer kennt sie nicht, die Selektor-Treppe:
.inhalt h2,
.inhalt h3,
.inhalt h4 { margin-top: 2rem; }
.karte h2,
.karte h3,
.karte h4 { margin-top: 1rem; }Bei zwei Containern sind das schon sechs Zeilen; bei vier Containern mit vier Elementtypen sechzehn. :is() nimmt eine Liste und gilt für jeden Treffer darin.
:is() – eine Liste statt vieler Zeilen
:is(.inhalt, .karte) :is(h2, h3, h4) {
margin-top: 2rem;
}Gleiche Wirkung, eine Zeile, und beim Hinzufügen eines Containers änderst du genau eine Stelle.
Der Haken: :is() erbt die höchste Spezifität aus seiner Liste
:is(#haupt, .karte) p { color: red; }Dieser Selektor wiegt so viel wie #haupt p – die stärkste Angabe in der Klammer zählt, auch wenn der Treffer über .karte zustande kam. Eine spätere Regel .karte p { color: blue; } verliert dann, und niemand versteht warum.
:where() – dieselbe Gruppierung, Gewicht null
:where(#haupt, .karte) p { color: red; }
.karte p { color: blue; } /* gewinnt */:where() zählt in der Spezifität als 0. Genau das macht es zum richtigen Werkzeug für alles, was überschreibbar bleiben soll: Grundstile, Resets, Vorgaben einer Komponentenbibliothek.
/* Basisabstände, die jede Seite ohne !important korrigieren darf */
:where(h1, h2, h3, p, ul, ol) { margin-block: 0 .75em; }
/* Bewusst stark: der aktive Zustand soll gewinnen */
:is(.tab, .pill).is-aktiv { border-color: var(--accent); }Nebenbei: verzeihende Fehlerbehandlung
In einer klassischen Selektorliste macht ein unbekannter Selektor die ganze Regel ungültig. Innerhalb von :is() und :where() wird nur der unbekannte Teil verworfen, der Rest greift weiter – praktisch, wenn du herstellerabhängige Pseudoelemente mischst:
:where(::-webkit-input-placeholder, ::placeholder) { color: #8b95a5; }Fallstrick
:is() und :where() dürfen (noch) nicht mit Pseudoelementen wie ::before in der Liste umgehen, und sie ersetzen keine Verschachtelung: Wer alles in :where() packt, hat am Ende ein Stylesheet ohne jedes Gewicht, in dem die Quellreihenfolge allein entscheidet. Die Mischung ist die Kunst – Grundlagen mit :where(), Zustände mit :is() oder ganz normalen Klassen.
Wartbares CSS ist kein Selbstzweck: Es entscheidet, wie teuer die nächste Änderung wird. Melde dich über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
@layer in CSS: Kaskadenebenen statt !important-Wettrüsten
Irgendwann steht in jedem gewachsenen Stylesheet das erste !important – und ein halbes Jahr später das dreißigste. Mit @layer legst du die Reihenfolge einmal fest, und ab da gewinnt nicht mehr der längste Selektor, sondern die Ebene, die du bestimmt hast.
content-visibility – lange Seiten rendern, ohne dass der Browser alles auf einmal baut
Bei sehr langen Seiten rechnet der Browser Layout und Malen für jeden Abschnitt – auch für die, die 8.000 Pixel weiter unten liegen. Eine CSS-Eigenschaft verschiebt diese Arbeit auf den Moment, in dem sie gebraucht wird.
color-mix() – Hover- und Dark-Mode-Farben ausrechnen lassen, statt sie zu pflegen
Für jede Markenfarbe eine hellere, eine dunklere und eine transparente Variante von Hand zu pflegen, ist Fleißarbeit mit Fehlerquote. color-mix() mischt sie im Browser – aus genau einer Quellfarbe.