CSS Nesting

Zuletzt aktualisiert am 3. Juli 2026

Im letzten Artikel hast du gelernt, wie die Kaskade entscheidet, welche Regel gewinnt. Dabei ist dir vielleicht aufgefallen, dass sich Selektoren in flachem CSS ständig wiederholen: .karte, .karte .titel, .karte .text, .karte:hover. CSS Nesting löst diese Wiederholung. Du schreibst Regeln direkt ineinander, und der Browser setzt die Selektoren selbst zusammen. Das funktioniert nativ in allen modernen Browsern, ein Build-Tool wie Sass brauchst du dafür nicht.

Selektoren verschachteln

Schauen wir uns zuerst an, wie eine Komponente in flachem CSS aussieht. Der Name .karte taucht in jeder einzelnen Regel auf:

.karte {
  border: 2px solid #1a56db;
  border-radius: 8px;
  padding: 16px;
}

.karte .titel {
  color: #1a56db;
  font-size: 18px;
}

.karte .text {
  color: #1e3a5f;
  font-size: 14px;
}

Mit Nesting schreibst du die Regeln für .titel und .text direkt in die .karte-Regel hinein:

Verschachtelte Selektoren
.karte {
  border: 2px solid #1a56db;
  border-radius: 8px;
  padding: 16px;

  .titel {
    color: #1a56db;
    font-size: 18px;
  }

  .text {
    color: #1e3a5f;
    font-size: 14px;
  }
}

Der Browser liest die innere Regel .titel als .karte .titel. Zwischen äußerem und innerem Selektor steht automatisch ein Leerzeichen, also der Nachfahren-Kombinator. Beide Schreibweisen erzeugen dasselbe Ergebnis, aber die verschachtelte Version hält alles, was zur Karte gehört, an einer Stelle zusammen.

Das funktioniert auch mit Element-Selektoren: p { ... } innerhalb von .karte wird zu .karte p.

Der &-Selektor

Das kaufmännische Und (&) steht innerhalb einer verschachtelten Regel für den äußeren Selektor. Du brauchst es immer dann, wenn der innere Selektor ohne Leerzeichen direkt am äußeren kleben soll.

Wann & nötig ist

Der wichtigste Fall sind Pseudoklassen und Modifier-Klassen:

& für Pseudoklassen und Modifier
.nav-link {
  color: #1a56db;
  text-decoration: none;

  &:hover {
    text-decoration: underline;
    color: #1e40af;
  }

  &.aktiv {
    font-weight: bold;
    color: #059669;
  }
}

Fahre mit der Maus über die Links: &:hover wird zu .nav-link:hover. Und &.aktiv wird zu .nav-link.aktiv, trifft also nur Elemente, die beide Klassen tragen. Der Link “Blog” ist deshalb grün und fett.

Ohne & würde etwas anderes passieren: :hover { ... } innerhalb von .nav-link bedeutet .nav-link :hover (mit Leerzeichen). Das trifft gehoverte Kind-Elemente des Links, nicht den Link selbst. Genauso wäre .aktiv { ... } gleichbedeutend mit .nav-link .aktiv, also einem Element mit der Klasse aktiv innerhalb des Links.

Wann du & weglassen kannst

Für Nachfahren-Regeln und Kombinatoren ist & optional. Diese Schreibweisen sind jeweils identisch:

.karte {
  .titel { }      /* wird zu: .karte .titel */
  & .titel { }    /* identisch: .karte .titel */

  p { }           /* wird zu: .karte p */
  > .zeile { }    /* wird zu: .karte > .zeile */
  + .karte { }    /* wird zu: .karte + .karte */
}

Die Faustregel: Soll ein Leerzeichen oder ein Kombinator zwischen den Selektoren stehen, kannst du & weglassen. Soll der innere Selektor direkt am äußeren hängen (.karte:hover, .karte.gross), brauchst du &.

& am Ende: den Kontext umdrehen

Du kannst & auch hinter einen anderen Selektor stellen. Dann fragst du: In welchem Umfeld steckt mein Element?

Kontext-Regel mit .theme-dark &
.button {
  background: #1a56db;
  color: #ffffff;

  .theme-dark & {
    background: #facc15;
    color: #1f2937;
  }
}

.theme-dark & wird zu .theme-dark .button: Derselbe Button bekommt andere Farben, sobald er in einem Element mit der Klasse theme-dark steckt. Die Regel steht trotzdem bei der Button-Komponente, wo du sie suchen würdest.

Media Queries verschachteln

Auch @media kannst du direkt in eine Regel schreiben. Die Media Query gilt dann für den umgebenden Selektor:

Media Query in der Regel
.karte {
  background: #dbeafe;
  border: 2px solid #1a56db;

  @media (min-width: 500px) {
    background: #d1fae5;
    border-color: #059669;
  }
}

Die Deklarationen innerhalb der Media Query gelten für .karte, sobald die Bedingung erfüllt ist. Das entspricht dieser flachen Schreibweise:

@media (min-width: 500px) {
  .karte {
    background: #d1fae5;
    border-color: #059669;
  }
}

Der Vorteil der verschachtelten Variante: Alle Regeln einer Komponente stehen beieinander, inklusive ihres responsiven Verhaltens. Du musst nicht ans Ende der Datei scrollen, um zu sehen, wie sich die Karte auf großen Bildschirmen verhält.

Unterschiede zu Sass

Wenn du Sass kennst, kommt dir Nesting bekannt vor. Es gibt aber wichtige Unterschiede:

MerkmalNatives CSS NestingSass
Compile-SchrittKeiner, läuft direkt im BrowserBuild-Tool nötig
&-BedeutungEchter Selektor, wirkt wie :is()Textersetzung beim Kompilieren
String-Verkettung (&__element)Nicht möglichMöglich
SpezifitätÄußerer Selektor zählt wie :is()Ergibt sich aus dem ausgeschriebenen Selektor
Media Queries verschachtelnJaJa

Der größte Stolperstein für Sass-Umsteiger ist die BEM-Schreibweise mit String-Verkettung:

/* Sass: wird beim Kompilieren zu .karte__titel */
.karte {
  &__titel {
    color: #1a56db;
  }
}

/* Natives CSS: funktioniert NICHT.
   & ist keine Textersetzung, die Regel wird verworfen. */

/* Stattdessen die Klasse ausschreiben: */
.karte {
  .karte__titel {
    color: #1a56db;
  }
}

In Sass ist & reiner Text, der beim Kompilieren eingesetzt wird. Deshalb kann Sass aus &__titel den Klassennamen .karte__titel zusammenbauen. In nativem CSS ist & ein echter Selektor, keine Zeichenkette. &__titel wäre die Kombination aus & und einem Element namens __titel, und das ist ungültige Syntax. Der Browser verwirft die komplette Regel.

Spezifität: der äußere Selektor zählt wie :is()

Nesting hat eine Eigenheit bei der Spezifität, die du kennen solltest. Der äußere Selektor fließt in die verschachtelte Regel so ein, als stünde er in einer :is()-Funktion. Und :is() bekommt immer die höchste Spezifität aus seiner Selektorliste, egal welcher Selektor tatsächlich getroffen hat.

Spezifität bei Selektorlisten
#haupt, .infobox {
  .hinweis {
    color: #059669;  /* Spezifität: 1-1-0 */
  }
}

.infobox .hinweis {
  color: #dc2626;    /* Spezifität: 0-2-0 */
}

Der Hinweis ist grün, obwohl die rote Regel später im Code steht und obwohl es gar kein Element mit der ID haupt gibt. Der Grund: Der Browser liest die verschachtelte Regel so:

:is(#haupt, .infobox) .hinweis {
  color: #059669;
}

:is(#haupt, .infobox) bekommt die Spezifität des stärksten Eintrags in der Liste, also 1-0-0 von der ID. Zusammen mit .hinweis (0-1-0) ergibt das 1-1-0. Die flache Regel .infobox .hinweis kommt nur auf 0-2-0 und verliert, wie du es aus dem Artikel über die Kaskade kennst: Die ID-Spalte schlägt jede Anzahl an Klassen.

Merke dir daraus zwei Dinge: Erstens erhöht eine ID in der äußeren Selektorliste die Spezifität aller verschachtelten Regeln. Zweitens verhält sich natives Nesting hier anders als Sass, wo #haupt .hinweis und .infobox .hinweis als zwei getrennte flache Regeln mit je eigener Spezifität herauskommen würden.

Wann Nesting den Code lesbarer macht

Nesting ist ein Werkzeug für Struktur, kein Selbstzweck. Es lohnt sich vor allem hier:

  • Komponenten mit ihren Zuständen: Hover, Focus und Modifier-Klassen (&:hover, &.aktiv) direkt bei der Komponente zu haben, macht den Zusammenhang sofort sichtbar.
  • Media Queries bei der Komponente: Das responsive Verhalten steht dort, wo die Komponente definiert ist, nicht hunderte Zeilen weiter unten.
  • Kleine, klar zusammengehörige Strukturen: Eine Karte mit Titel und Text, eine Navigation mit Links. Eine oder zwei Ebenen Verschachtelung reichen dafür.

Flaches CSS bleibt die bessere Wahl, wenn:

  • Die Verschachtelung nur das HTML nachbaut: Wer .seite .inhalt .artikel .absatz verschachtelt, koppelt das CSS an die DOM-Struktur. Ändert sich das HTML, bricht das Styling. Eine flache Klasse wie .artikel-text ist robuster.
  • Klassen wiederverwendbar sein sollen: Utility-Klassen wie .hidden oder .text-center gehören nicht in eine Verschachtelung, sonst gelten sie nur noch in diesem Kontext.
  • Selektoren auffindbar bleiben müssen: Bei verschachteltem Code steht der vollständige Selektor .karte .titel nirgendwo im Quelltext. Wer per Textsuche debuggt, findet ihn nicht auf Anhieb.

Als Faustregel: Maximal zwei, in Ausnahmen drei Ebenen. Wenn du tiefer verschachtelst, ist das meistens ein Zeichen, dass eine eigene Klasse die klarere Lösung wäre.

Häufige Fehler

  • String-Verkettung wie in Sass erwarten: &__titel funktioniert in nativem CSS nicht, die Regel wird komplett verworfen. Schreibe die vollständige Klasse aus (.karte__titel).
  • & bei Pseudoklassen vergessen: :hover { ... } innerhalb von .button bedeutet .button :hover mit Nachfahren-Kombinator, nicht .button:hover. Für Zustände des Elements selbst immer &:hover schreiben.
  • Zu tief verschachteln: Jede Ebene erhöht die Spezifität und koppelt das CSS enger an die HTML-Struktur. Was du in flachem CSS als “zu viele verkettete Selektoren” vermeiden würdest, entsteht beim Nesting fast von allein.
  • IDs in der äußeren Selektorliste unterschätzen: Wegen des :is()-Verhaltens hebt eine einzige ID die Spezifität aller verschachtelten Regeln auf ID-Niveau. Solche Regeln lassen sich später kaum noch überschreiben.
  • Eigenschaften und verschachtelte Regeln mischen: Schreibe erst alle Deklarationen der äußeren Regel, dann die verschachtelten Regeln. Deklarationen, die nach einer verschachtelten Regel stehen, werden zwar angewendet, sind beim Lesen aber leicht zu übersehen.

Zusammenfassung

KonzeptBeschreibung
NestingRegeln direkt in anderen Regeln schreiben, ohne Build-Tool
Nachfahren.titel { } in .karte wirkt wie .karte .titel
&Steht für den äußeren Selektor
&:hover, &.aktiv& ist Pflicht, wenn kein Leerzeichen entstehen soll
.kontext &Dreht die Richtung um: Element innerhalb von .kontext
@media in RegelnMedia Query gilt für den umgebenden Selektor
SpezifitätÄußerer Selektor zählt wie :is(): höchster Wert der Liste
Kein SassKeine String-Verkettung wie &__element, kein Compile-Schritt

Du kannst jetzt zusammengehörige Regeln bündeln und entscheiden, wann Verschachtelung hilft und wann flaches CSS die bessere Wahl bleibt. Im nächsten Artikel geht es um das Box-Modell: Das Fundament für Abstände, Rahmen und Größen in CSS.

Bleib auf dem Laufenden

Erhalte neue Inhalte direkt in dein Postfach

Mit der Anmeldung akzeptierst du unsere Datenschutzerklärung. Du kannst dich jederzeit über den Link in den E-Mails wieder abmelden.

Was erwartet dich?

Neue Artikel & Videos

Wenn ich was Neues veröffentliche, erfährst du's hier zuerst.

Plattform & Kurs-Updates

Neue Kurse, Referenz-Updates und gelegentlich Sonderpreise zum Launch.

Einmal die Woche in deinem Postfach

Kurz, auf den Punkt, kein Spam.