The StyleWorksCSS { Referenz · Labor · Übungen }
  1. Startseite
  2. CSS 3 und neuer
  3. CSS Selektoren Level 3

CSS 3 und neuer · Modul

Neue CSS Selektoren seit CSS 2.1: :nth-child, :not(), Attributselektoren und die Pseudoelemente mit zwei Doppelpunkten

CSS 2.1 kennt :first-child, aber nicht :last-child; Attributselektoren, aber keine Teilstring-Vergleiche; :before mit einem Doppelpunkt. Selectors Level 3 und 4 schließen die Lücken: Positionen, Verneinung, Zustände von Formularen, :is() und :has().

Veröffentlicht Lesezeit 3 minGrundlage CSS 2.1
stylesheet.css · li:nth-child(odd)
li:nth-child(odd) {
  outline: 2px solid #7A2FB0;
}

Überschrift

Erster Absatz direkt nach der Überschrift, mit einem Link und einem Zitat.

Zweiter Absatz, Klasse extra.

  • Erster Listenpunkt
  • Zweiter Listenpunkt mit Link
  • Dritter Listenpunkt

Dritter Absatz, ohne Klasse.

Selektorli:nth-child(odd)
Treffer
Spezifität

Strukturelle Pseudoklassen: nth-child, last-child, only-child

:first-child aus CSS 2.1 bekommt Geschwister: :last-child, :only-child, :nth-child(n) mit einer Formel – :nth-child(odd), :nth-child(3n+1) – und :nth-last-child() vom Ende. :nth-of-type() zählt nur Geschwister desselben Typs; :empty trifft Elemente ohne Kinder. Streifen in Tabellen, das letzte Element ohne Trennlinie, jedes dritte Bild in einer Reihe – Aufgaben, für die CSS 2.1 Klassen im HTML verlangte.

tr:nth-child(even)  { background: #F3ECFA; }
li:last-child       { border-bottom: 0; }
.reihe img:nth-of-type(3n) { margin-right: 0; }

Attributselektoren mit Teilstrings

CSS 2.1 vergleicht Attribute auf Gleichheit (=), Wort in einer Liste (~=) und Sprachpräfix (|=). Level 3 ergänzt ^= (beginnt mit), $= (endet auf) und *= (enthält). a[href^="http"] trifft externe Links, a[href$=".pdf"] PDF-Verweise, [class*="icon-"] jede Klasse mit diesem Bestandteil. Die Referenz zu Attributselektoren beschreibt die Grundformen.

:not(), :is(), :where(), :has()

:not(.aktiv) verneint; die Spezifität ist die des Arguments. :is(h1, h2, h3) a fasst Alternativen zusammen und nimmt die Spezifität des spezifischsten Arguments; :where() tut dasselbe mit Spezifität null – nützlich für Grundregeln, die jede spätere Regel überschreiben soll. :has() ist der lange vermisste Elternselektor: label:has(input:checked) trifft das Label eines angehakten Kästchens, article:has(img) Artikel mit Bild. Alle vier funktionieren seit 2023 in allen verbreiteten Browsern.

Pseudoelemente mit zwei Doppelpunkten

Level 3 schreibt Pseudoelemente mit ::, um sie von Pseudoklassen zu unterscheiden: ::before, ::after, ::first-letter, ::first-line. Die Schreibweise mit einem Doppelpunkt aus CSS 2.1 bleibt für diese vier gültig. Neu sind ::selection (markierter Text), ::marker (Aufzählungszeichen), ::placeholder und ::backdrop. Die Referenz zu :before und :after erklärt generierten Inhalt.

Die Spezifität der neuen Pseudoklassen

Die logischen Pseudoklassen verhalten sich in der Spezifität unterschiedlich, und das ist ihr eigentlicher Zweck. :is() und :not() zählen so viel wie ihr stärkstes Argument – :is(.karte, #haupt) wiegt also so schwer wie eine Kennung, auch wenn im Dokument die Klasse trifft. :where() zählt dagegen null, egal was darin steht, und ist damit die einzige Möglichkeit, mehrere Selektoren zusammenzufassen, ohne die Spezifität anzuheben.

Daraus ergibt sich eine praktische Aufteilung. Für Grundregeln, die überall leicht überschreibbar bleiben sollen – die Vorgaben eines Bausteins, ein Zurücksetzen –, ist :where() richtig. Für gezielte Regeln, die sich durchsetzen sollen, ist :is() richtig. Und wer eine lange Selektorliste durch :is() ersetzt, sollte nachrechnen: Die Liste hatte für jeden Teil eine eigene Spezifität, die Zusammenfassung hat für alle die höchste.

Selektoren, die rückwärts schauen

:has() ist der erste Selektor, mit dem sich ein Element danach auswählen lässt, was in ihm oder hinter ihm steht – eine Karte mit Bild anders gestalten als eine ohne, eine Beschriftung nach einem ungültigen Feld einfärben. Bis dahin ging das nur mit einem Skript oder einer zusätzlichen Klasse im Dokument, und beides bedeutete, den Zustand an zwei Stellen zu pflegen.

Der Verdacht, das sei zwangsläufig langsam, hat sich nicht bestätigt: Die Browser werten Selektoren von rechts nach links aus und behandeln die Rückwärtssuche als eigenen Schritt, der nur für die in Frage kommenden Elemente läuft. Teuer wird es dort, wo die Bedingung über einen weiten Bereich des Baumes reicht und sich oft ändert – etwa eine Bedingung am Wurzelelement, die von einem Zustand tief unten abhängt. Die Faustregel lautet deshalb, die Bedingung so nah wie möglich an das gestaltete Element zu legen, und nicht, den Selektor zu meiden.

Verschachtelung im Stylesheet selbst

Die jüngste Erweiterung betrifft nicht einzelne Selektoren, sondern ihre Schreibweise: Regeln dürfen ineinander stehen, und der innere Selektor bezieht sich auf den äußeren. Was jahrelang nur mit einem Vorverarbeiter ging, ist damit Bestandteil der Sprache. Auf den äußeren Selektor lässt sich mit einem eigenen Zeichen ausdrücklich verweisen, etwa um einen Zustand oder eine Bedingung anzuhängen.

Die Verschachtelung ändert nichts an der Spezifität einer Regel – gezählt wird der ausgeschriebene Selektor, den sie ergibt. Genau das ist die Falle: Drei Ebenen Verschachtelung lesen sich übersichtlich und ergeben einen Selektor mit drei Klassen, der später schwer zu überschreiben ist. Die Empfehlung lautet deshalb, die Verschachtelung für Zustände, Bedingungen und Bausteinteile zu nutzen und nicht dazu, die Struktur des Dokuments im Stylesheet nachzubauen.

Zustände: focus-visible, checked, disabled, target

:checked, :disabled, :required, :valid und :invalid gestalten Formulare nach Zustand, ohne Skript. :focus-visible zeigt den Fokusring nur, wenn er per Tastatur gesetzt wurde. :target trifft das Element, dessen ID im Fragment der Adresse steht. Die dynamischen Pseudoklassen aus CSS 2.1 – :hover, :active, :focus – bleiben unverändert.

Häufige Fragen

Was ist der Unterschied zwischen :nth-child und :nth-of-type?

:nth-child(n) zählt alle Geschwister, :nth-of-type(n) nur die desselben Elementtyps. p:nth-child(2) trifft einen Absatz nur, wenn er das zweite Kind ist; p:nth-of-type(2) den zweiten Absatz unter den Geschwistern.

Welche Spezifität hat :not()?

Die seines Arguments. :not(.aktiv) zählt wie eine Klasse, :not(#kopf) wie eine ID. Die Pseudoklasse selbst fügt nichts hinzu.

Was ist der Unterschied zwischen :is() und :where()?

Beide fassen Alternativen zusammen. :is() hat die Spezifität des spezifischsten Arguments, :where() immer null – für Grundregeln, die leicht überschreibbar bleiben sollen.

Gibt es einen Elternselektor in CSS?

Ja, seit :has(): li:has(> a.aktiv) trifft das Listenelement, das einen aktiven Link enthält. Unterstützt seit 2023 in allen verbreiteten Browsern.

Muss man ::before mit zwei Doppelpunkten schreiben?

Empfohlen ja, um Pseudoelemente von Pseudoklassen zu unterscheiden. Für before, after, first-letter und first-line bleibt die alte Schreibweise mit einem Doppelpunkt gültig.

Wie gestaltet man ein angehaktes Kontrollkästchen mit CSS?

Mit input:checked für das Feld selbst und label:has(input:checked) für sein Label – ohne JavaScript.