Abschnitt 15 · Lektion 2
CSS Nesting
Eine Komponente besteht selten aus einer Regel. Die Karte hat eine Grundregel, dazu eine für ihre Überschrift, eine für den Absatz, eine für den Button und eine für den Zustand beim Überfahren. Flach geschrieben sind das fünf Regeln, die alle mit .karte anfangen. Im Lauf eines Jahres driften sie langsam auseinander.
Verschachteln ändert nichts am Ergebnis. Es ändert nur, wo die Regeln stehen, nämlich alle im selben Block, eingerückt unter der Komponente, zu der sie gehören. Das konnte lange nur Sass. Seit Dezember 2023 kann es jeder große Browser selbst, und seit Juni 2026 steht es bei Baseline auf „Widely available“.
In älteren Anleitungen steht noch vor jedem verschachtelten Elementnamen ein &, also & h3 statt h3, weil die ersten Browser es anders nicht verstanden. Heute geht beides.
Der innere Selektor ist relativ
<article class="karte">
<h3>Tipptrainer</h3>
<p>Zehnfinger im Browser, ohne Anmeldung.</p>
<a class="button" href="#">Ansehen</a>
</article> *,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.karte {
max-width: 340px;
padding: 24px;
border: 1px solid #d4d4d8;
border-radius: 12px;
/* Gilt für h3 innerhalb von .karte */
h3 {
margin: 0 0 8px 0;
font-size: 20px;
}
p {
margin: 0;
color: #52525b;
}
/* Das & meint die Karte selbst, nicht ihre Kinder. */
&:hover {
border-color: #2563eb;
}
.button {
display: inline-flex;
align-items: center;
min-height: 44px;
margin-top: 16px;
padding: 0 16px;
border-radius: 8px;
text-decoration: none;
color: #ffffff;
background-color: #2563eb;
}
} Ein Selektor innerhalb eines Blocks gilt relativ zum äußeren. h3 innerhalb von .karte bedeutet .karte h3, also jede Überschrift innerhalb der Karte. Genauso wird .button innerhalb von .karte zu .karte .button.
Das Ergebnis ist identisch mit der flachen Schreibweise. Der Browser baut daraus dieselben Selektoren, die du sonst von Hand geschrieben hättest.
Im Reiter „Werte“ findest du deshalb ausnahmsweise nichts Besonderes. Dort steht das Ergebnis, und das ist in beiden Schreibweisen dasselbe. An der Karte padding: 24px und border: 1px solid rgb(37, 99, 235), an der Überschrift font-size: 20px, am Button margin: 16px 0px 0px und height: 44px. Schreibst du dieselben Regeln flach daneben, ändert sich kein einziger Wert. Verschachteln ist eine Frage der Ordnung im Stylesheet, nicht des Ergebnisses.
Im Reiter „Regeln“ steht dagegen, was im Stylesheet steht, an der Überschrift also & h3 statt .karte h3. Das ist der einzige Unterschied, und es ist nur einer der Schreibweise, denn die Zahl daneben ist in beiden Fällen 0-1-1. Das kaufmännische Und trägt die Spezifität der Regel drumherum, hier also die einer Klasse. An der Kaskade ändert Verschachteln deshalb nichts.
Das & meint das Element selbst
<article class="karte">
<h3>Fahr über die Karte</h3>
<p>Der Rahmen sollte blau werden. Tut er aber nur,
wenn du genau über diesem Absatz stehst.</p>
</article> body {
margin: 0;
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.karte {
max-width: 340px;
padding: 24px;
border: 2px solid #d4d4d8;
border-radius: 12px;
h3 {
margin: 0 0 8px 0;
font-size: 20px;
}
/* Der Absatz hat einen unsichtbaren Rahmen. Ohne
border-style wäre auch die Rahmenbreite null,
und man sähe die Färbung gleich gar nicht. */
p {
margin: 0;
padding: 8px;
border: 2px solid transparent;
border-radius: 8px;
}
/* Hier fehlt das &. Der Browser liest das als
".karte :hover", also als Nachfahre, und färbt
den Rahmen des Absatzes statt den der Karte. */
:hover {
border-color: #2563eb;
}
} Hier liegt die eine Falle. Ohne & wird ein Nachfahre daraus. :hover innerhalb von .karte heißt .karte :hover, also jedes Kind unter dem Zeiger, und eben nicht die Karte selbst.
Gemeint ist fast immer &:hover, und dasselbe gilt für &:focus-within, &.ist-offen und &[aria-current="page"]. Wenn der zusätzliche Teil direkt am Element hängt, brauchst du das &.
Es geht auch andersherum. .dunkel & innerhalb von .karte ergibt .dunkel .karte. So schreibst du die Dunkelmodus-Variante an die Komponente, obwohl der Auslöser weit oben im Baum sitzt.
Was hier anders ist als in Sass
In Sass kann man & mit Text zusammenkleben und aus &__titel innerhalb von .karte die Klasse .karte__titel bauen. Das geht im Browser nicht. & ist dort ein vollwertiger Selektor und kein Textbaustein. &__titel ist deshalb gar kein Selektor. __titel läse der Browser als Elementnamen, und der müsste in einem zusammengesetzten Selektor vorne stehen. Die Regel ist ungültig und fliegt raus.
Die Namen aus Abschnitt 16 schreibe ich deshalb aus, also .karte__titel { ... } innerhalb des Blocks und nicht abgekürzt. Das ist etwas mehr Tipparbeit. Dafür findest du den vollen Namen später mit der Suche wieder.
Media Queries gehören zur Komponente
<div class="reihe">
<article class="karte"><h3>Eins</h3></article>
<article class="karte"><h3>Zwei</h3></article>
</div>
<p class="hinweis">Zieh die Trennlinie nach links, bis die Seite über 600 Pixel breit ist.</p> body {
margin: 0;
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.reihe {
display: grid;
gap: 12px;
grid-template-columns: 1fr;
/* Die Ausnahme steht bei der Regel, für die sie gilt,
statt am Ende der Datei bei allen anderen. */
@media (min-width: 37.5rem) {
grid-template-columns: 1fr 1fr;
}
}
.karte {
padding: 16px;
border: 1px solid #d4d4d8;
border-radius: 12px;
h3 {
margin: 0;
font-size: 18px;
}
}
.hinweis {
color: #52525b;
} @media und @container lassen sich ebenfalls verschachteln. Erst hier bringt Verschachteln wirklich etwas, denn die Ausnahme für breite Bildschirme steht direkt bei der Regel, für die sie gilt, statt zweihundert Zeilen weiter unten in einem Sammelblock.
In der schmalen Spalte siehst du davon nichts. Dort ist die Seite 380 Pixel breit, und die Ausnahme greift erst ab 37.5rem, also 600 Pixel. Ziehst du die Trennlinie weiter nach links, wird die Seite breit genug, und bei 740 Pixeln steht im Streifen grid-template-columns: 340px 340px statt der einen Spur 332px davor.
Zwei Ebenen, nicht fünf
Mit jeder Ebene steigt die Spezifität, weil aus jedem Schritt ein weiterer Selektorteil wird. Wer vier Ebenen tief verschachtelt, baut sich genau die langen Selektorketten, die in Abschnitt 3 schon Ärger gemacht haben. Nur sieht man sie jetzt nicht mehr.
Dazu kommt eine Feinheit. Das & verhält sich wie ein :is() um die äußere Selektorliste und nimmt deren höchste Spezifität. Steht außen h3, #titel, dann rechnet jede verschachtelte Regel darunter mit der ID, auch die, die eigentlich nur die Überschrift meint. In eine äußere Zeile schreibe ich deshalb nie eine ID neben eine Klasse.
Ich verschachtele selten tiefer als zwei Ebenen. Brauche ich eine dritte, ist meistens eine eigene Klasse fällig.
In der Aufgabe steht das Anmeldefeld für den Newsletter noch ohne eine einzige eigene Regel.
Zum Mitnehmen
Ein verschachtelter Selektor gilt relativ zum äußeren, h3 in .karte heißt .karte h3. Was direkt am Element hängt, braucht das &, sonst wird aus :hover ein Nachfahre.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
Was in dieser Lektion steckt
-
Artikel mit 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe im Editor, direkt im Browser geprüft
Öffnet sich mit dem Basis Konto.