:has() – Parent-Selektor
Der :has()-Selektor trifft auf alle Elemente zu, die mindestens ein bestimmtes Element enthalten. Wenn ein Element z.B. zusätzlich ein Bild neben dem Text enthält, weist das CSS dem Element display: flex zu. Das macht den has-Selektor zum Eltern- oder Parent-Selektor.
:has() – sag uns Vorfahre, hast du die richtigen Nachkommen?
Der :has-Selektor erlaubt CSS-Stile abhängig vom Inhalt eines Elements und erweitert CSS um die Pseudoklasse des Vorfahren- oder Parent-Selectors.
In einem dynamischen Navigationsmenü stellt :has fest, ob ein Menü-Element ein Untermenü enthält. (Browser, die :has nicht unterstützen, zeigen kein vorangestelltes ▶-Zeichen).
<ul class="hasmenu"> <li> Home </li> <li> Blog <ul> <li> Tipps </li> … </ul> </li> <li> Kosten <ul> <li> Entwicklung </li> … </ul> </li> … </ul>
ul.hasmenu ul { max-height: 0; overflow: hidden; } ul.hasmenu li:has(ul)::before { content: "▶"; }
ul.hasmenu li:has(ul)::before liest sich »Wenn ein li-Element unterhalb von ul.hasmenu ein weiteres ul-Element enthält, dann setze ▶ als Zeichen, dass hier mehr zu holen ist».
Browser-Support für :has
Safari und Chrome (ab Version 105)/Edge unterstützen :has() seit Ende 2022, Firefox ist erst seit Ende 2023 mit Version 121 dabei.
- Karten ohne Bild bleiben neutral,
- Karten mit einem Bild bekommen einen Rahmen und Hintergrundfarbe,
- Karten mit einem Call to Action-Button werden mit Hintergrundfarbe und Rahmen markiert.
Alles passiert rein mit CSS :has(), ohne extra Klassen oder JavaScript.
Diese Karte hat nur Text.

Hier ist zusätzlich ein Bild enthalten.
Karte mit Call to Action-Button.

Hier ist zusätzlich ein Bild enthalten.

Karte mit Call to Action-Button.

Hier ist zusätzlich ein Bild enthalten.
/* Karte mit Bild bekommt spezielle Optik */ .card:has(img) { border-color: teal; background: #f0fdfa; } /* Karte mit Button wird hervorgehoben */ .card:has(.btn-primary) { border-color: rebeccapurple; background: #f9f5ff; box-shadow: 0 0 10px rgba(102, 51, 153, 0.3); }
Navigations-Menü mit :has()
:has() kann CSS-seitig ohne Checkbox-Hack umschalten. Will man aber einen echten Toggle mit dauerhaftem Zustand (Klick = auf, nochmal Klick = zu), braucht man entweder :target oder 1–2 Zeilen JavaScript, um aria-expanded zu setzen.
<nav class="nav"> <button class="nav__toggle" aria-expanded="false">☰ Menü</button> <ul class="nav__list"> <li><a href="#">Start</a></li> <li><a href="#">Über uns</a></li> <li><a href="#">Leistungen</a></li> <li><a href="#">Kontakt</a></li> </ul> </nav>
Elemente mit CSS :has zählen
Mit :has() holt CSS ein weiteres Umfeld, das bislang Javascript vorbehalten war: :has zählt die Kind-Elemente eines übergeordneten Blocks.
Wenn ein Element der Klasse .block-columns zwei Kind-Elemente hat, ist sein Hintergrund dunkelgrau. Mit drei Kind-Elementen ist der Hintergrund mittelgrau, mit vier Kind-Elementen hellgrau.
.block-columns:has(.block-column:nth-child(2)) { background: #888; } .block-columns:has(.block-column:nth-child(3)) { background: #bbb; } .block-columns:has(.block-column:nth-child(4)) { background: #eee; }
Idee von Parents counting children in CSS.
Das CSS für das dynamische Menü oben (das klassisch aus ul mit li-Elementen besteht) zählt die li-Elemente und verteilt sie automatisch.
- Home
- Blog
- Tipps
- Technik
- Layout
- Kosten
- Entwicklung
- Sichern, Pflegen, Erweitern
- Datenschutz
- Impressum
ul.counter:has(li:nth-child(5)) li { background: cornflowerblue; width: 18%; padding:6px; }
Der andere Zähler für die Anzahl von Elementen ist CSS counter, der allerdings auf die sichtbare gerenderte Anzeige eine Index bzw. Ordnungszahl ausgerichtet ist.
:not-Selektor
Der :not()-Selector ist sozusagen das Gegenstück zu :has(). :not wird bereits seit längerer Zeit von allen modernen Browsern unterstützt.
Pseudo-Klassen vs Pseudo-Elemente
Pseudo-Klassen (einfacher Doppelpunkt) beschreiben einen Zustand eines Elements und können mit anderen CSS-Selektoren kombiniert werden, um Zustände sichtbar in die Webseite zu tragen. Das gängigste Beispiel ist ein :hover, das die Darstellung eines Links ändert, wenn der Benutzer die Maus über einem Element bewegt.
Pseudo-Elemente (doppelter Doppelpunkt) sprechen Teile eines Elements ohne HTML-Markup an, z.B. die erste Zeile eines Absatzes (::firstLine) und können Elemente ohne HTML-Markup einfügen (::before, ::after) oder einfach nur stylen (::marker – die Marker-Box von Listen). Sie können nicht inline in einem style-Attribut vereinbart werden und nur am Ende der Selektor-Kette stehen.