CSS-Verschachtelung

Eine unserer Lieblingsfunktionen des CSS-Präprozessors ist jetzt in die Sprache integriert: verschachtelte Stilregeln.

Adam Argyle
Adam Argyle

Vor dem Verschachteln musste jeder Selektor explizit und getrennt voneinander deklariert werden. Dies führt zu Wiederholungen, einem großen Stylesheet-Volumen und einer unübersichtlichen Autorenansicht.

Vorher
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

Nach dem Verschachteln können Selektoren fortgesetzt und zugehörige Stilregeln darin gruppiert werden.

Nachher
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Testen Sie das im Browser.

Durch das Verschachteln müssen Entwickler weniger Auswahlen wiederholen und können Stilregeln für zugehörige Elemente an einer Stelle platzieren. Außerdem können Sie so dafür sorgen, dass die Stile zum HTML-Code passen, auf den sie ausgerichtet sind. Wenn die .nesting-Komponente im vorherigen Beispiel aus dem Projekt entfernt wurde, können Sie die gesamte Gruppe löschen, anstatt in Dateien nach zugehörigen Auswahlinstanzen zu suchen.

Verschachtelung kann bei Folgendem helfen: - Organisation - Reduzierung der Dateigröße - Refactoring

Die Verschachtelung ist ab Chrome 112 verfügbar und kann auch in der Safari-Technischen Vorschau 162 getestet werden.

Erste Schritte mit CSS-Verschachtelung

Im restlichen Teil dieses Artikels wird die folgende Demo-Sandbox verwendet,um die Auswahlen zu veranschaulichen. In diesem Standardstatus ist nichts ausgewählt und alles ist sichtbar. Wenn Sie die verschiedenen Formen und Größen auswählen, können Sie die Syntax üben und in Aktion sehen.

Ein buntes Raster aus kleinen und großen Kreisen, Dreiecken und Quadraten.

In der Sandbox sind Kreise, Dreiecke und Quadrate zu sehen. Einige sind klein, mittel oder groß. Andere sind blau, rosa oder lila. Sie befinden sich alle im enthaltenden .demo-Element. Unten sehen Sie eine Vorschau der HTML-Elemente, auf die Sie das Targeting vornehmen.

<div class="demo">
  <div class="sm triangle pink"></div>
  <div class="sm triangle blue"></div>
  <div class="square blue"></div>
  <div class="sm square pink"></div>
  <div class="sm square blue"></div>
  <div class="circle pink"></div>
  …
</div>

Beispiele für Verschachtelung

Mithilfe von CSS-Verschachtelungen können Sie Stile für ein Element im Kontext eines anderen Selektors definieren.

.parent {
  color: blue;

  .child {
    color: red;
  }
}

In diesem Beispiel ist der .child-Klassen-Selektor im .parent-Klassen-Selektor verschachtelt. Das bedeutet, dass die verschachtelte .child-Auswahl nur auf Elemente angewendet wird, die untergeordneten Elementen mit der Klasse .parent sind.

Dieses Beispiel könnte alternativ mit dem Symbol & geschrieben werden, um anzugeben, wo die übergeordnete Klasse platziert werden soll.

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

Diese beiden Beispiele sind funktional gleichwertig. Der Grund, warum Sie Optionen haben, wird klarer, wenn in diesem Artikel fortgeschrittenere Beispiele erläutert werden.

Kreise auswählen

In diesem ersten Beispiel geht es darum, Stile hinzuzufügen, um nur die Kreise in der Demo auszublenden und zu verwischen.

Ohne Verschachtelung:

.demo .circle {
  opacity: .25;
  filter: blur(25px);
}

Bei Verschachtelungen gibt es zwei gültige Möglichkeiten:

/* & is explicitly placed in front of .circle */
.demo {
  & .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

oder

/* & + " " space is added for you */
.demo {
  .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

Ergebnis: Alle Elemente in .demo mit der Klasse .circle sind verschwommen und fast unsichtbar:

Das bunte Raster aus Formen enthält keine Kreise mehr, sie sind nur noch sehr schwach im Hintergrund zu sehen.
Demo testen

Dreiecke und Quadrate auswählen

Dazu müssen mehrere verschachtelte Elemente ausgewählt werden, auch als Gruppenauswahl bezeichnet.

Ohne Verschachtelung gibt es in CSS heute zwei Möglichkeiten:

.demo .triangle,
.demo .square {
  opacity: .25;
  filter: blur(25px);
}

oder mit :is()

/* grouped with :is() */
.demo :is(.triangle, .square) {
  opacity: .25;
  filter: blur(25px);
}

Bei Verschachtelung gibt es zwei gültige Möglichkeiten:

.demo {
  & .triangle,
  & .square {
    opacity: .25;
    filter: blur(25px);
  }
}

oder

.demo {
  .triangle, .square {
    opacity: .25;
    filter: blur(25px);
  }
}

Ergebnis: Innerhalb von .demo sind nur noch .circle-Elemente vorhanden:

Im bunten Raster aus Formen sind nur noch Kreise zu sehen, alle anderen Formen sind fast unsichtbar.
Demo testen

Große Dreiecke und Kreise auswählen

Für diese Aufgabe ist ein zusammengesetzter Selektor erforderlich, bei dem Elemente beide Klassen haben müssen, um ausgewählt zu werden.

Ohne Verschachtelung:

.demo .lg.triangle,
.demo .lg.square {
  opacity: .25;
  filter: blur(25px);
}

oder

.demo .lg:is(.triangle, .circle) {
  opacity: .25;
  filter: blur(25px);
}

Bei Verschachtelung gibt es zwei gültige Möglichkeiten:

.demo {
  .lg.triangle,
  .lg.circle {
    opacity: .25;
    filter: blur(25px);
  }
}

oder

.demo {
  .lg {
    &.triangle,
    &.circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

Ergebnis: Alle großen Dreiecke und Kreise sind in .demo verborgen:

Im bunten Raster sind nur kleine und mittelgroße Formen zu sehen.
Demo testen
Profitipp zu zusammengesetzten Auswahlen und Verschachtelung

Das Symbol & ist hier Ihr Freund, da es explizit zeigt, wie verschachtelte Auswahlen aneinandergefügt werden. Dazu ein Beispiel:

.demo {
  .lg {
    .triangle,
    .circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

Das ist zwar eine gültige Verschachtelung, die Ergebnisse stimmen jedoch nicht mit den erwarteten Elementen überein. Das liegt daran, dass ohne &, um das gewünschte Ergebnis der zusammengesetzten .lg.triangle, .lg.circle anzugeben, das tatsächliche Ergebnis .lg .triangle, .lg .circle wäre; Abkömmlingsauswahlen.

Alle Formen außer den rosafarbenen auswählen

Für diese Aufgabe ist eine funktionale Pseudoklasse für die Negation erforderlich, bei der Elemente nicht den angegebenen Selektor haben dürfen.

Ohne Verschachtelung:

.demo :not(.pink) {
  opacity: .25;
  filter: blur(25px);
}

Bei Verschachtelung gibt es zwei gültige Möglichkeiten:

.demo {
  :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

oder

.demo {
  & :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

Ergebnis: Alle Formen, die nicht rosa sind, sind in .demo ausgeblendet:

Das bunte Raster ist jetzt einfarbig und zeigt nur rosafarbene Formen.
Demo testen
Präzision und Flexibilität mit &

Angenommen, Sie möchten die Auswahl :not() auf .demo ausrichten. & ist erforderlich für Folgendes:

.demo {
  &:not() {
    ...
  }
}

Dadurch werden .demo und :not() zu .demo:not() kombiniert, im Gegensatz zum vorherigen Beispiel, in dem .demo :not() erforderlich war. Diese Erinnerung ist sehr wichtig, wenn Sie eine :hover-Interaktion verschachteln möchten.

.demo {
  &:hover {
    /* .demo:hover */
  }

  :hover {
    /* .demo :hover */
  }
}

Weitere Beispiele für Verschachtelung

Die CSS-Spezifikation für das Verschachteln enthält weitere Beispiele. Wenn Sie mehr über die Syntax erfahren möchten, finden Sie dort eine Vielzahl gültiger und ungültiger Beispiele.

In den nächsten Beispielen wird kurz eine CSS-Verschachtelungsfunktion vorgestellt, damit Sie die Vielfalt der damit verbundenen Funktionen besser nachvollziehen können.

@media-Verschachtelung

Es kann sehr ablenkend sein, zu einem anderen Bereich des Stylesheets zu wechseln, um Bedingungen für Medienabfragen zu finden, die einen Auswählen und seine Stile ändern. Diese Ablenkung ist nicht mehr vorhanden, da die Bedingungen direkt im Kontext verschachtelt werden können.

Wenn die verschachtelte Medienabfrage nur die Stile für den aktuellen Auswahlkontext ändert, kann aus Gründen der Übersichtlichkeit eine minimale Syntax verwendet werden.

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    font-size: 1.25rem;
  }
}

Die explizite Verwendung von & kann auch für Folgendes verwendet werden:

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    &.large {
      font-size: 1.25rem;
    }
  }
}

In diesem Beispiel wird die erweiterte Syntax mit & gezeigt. Außerdem wird die Ausrichtung auf .large-Karten verwendet, um zu zeigen, dass zusätzliche Verschachtelungsfunktionen weiterhin funktionieren.

Weitere Informationen zum Verschachteln von @rules

Verschachteln an beliebiger Stelle

Alle bisherigen Beispiele haben einen vorherigen Kontext fortgesetzt oder an ihn angehängt. Sie können den Kontext bei Bedarf vollständig ändern oder neu anordnen.

.card {
  .featured & {
    /* .featured .card */
  }
}

Das Symbol & steht für einen Verweis auf ein Auswahlobjekt (kein String) und kann an einer beliebigen Stelle in einer verschachtelten Auswahl platziert werden. Sie kann sogar mehrmals platziert werden:

.card {
  .featured & & & {
    /* .featured .card .card .card */
  }
}

Dieses Beispiel mag zwar etwas unnötig erscheinen, aber es gibt durchaus Szenarien, in denen es praktisch ist, einen Auswahlkontext wiederholen zu können.

Beispiele für ungültige Verschachtelung

Es gibt einige ungültige Syntaxszenarien für Verschachtelungen, die Sie vielleicht überraschen, wenn Sie in Preprocessorn verschachtelt haben.

Verschachtelung und Verkettung

Viele CSS-Namenskonventionen für Klassen setzen voraus, dass durch Verschachtelung Selektoren wie Strings zusammengefügt oder angehängt werden können. Dies funktioniert nicht bei CSS-Verschachtelungen, da die Selektoren keine Strings, sondern Objektverweise sind.

.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}

Eine ausführlichere Erklärung finden Sie in der Spezifikation.

Beispiel für eine knifflige Verschachtelung

Verschachtelung in Selektorlisten und :is()

Betrachten Sie den folgenden verschachtelten CSS-Block:

.one, #two {
  .three {
    /* some styles */
  }
}

Dies ist das erste Beispiel, das mit einer Auswahlliste beginnt und dann weiter verschachtelt wird. Die vorherigen Beispiele endeten nur mit einer Auswahlliste. Dieses Verschachtelungsbeispiel ist nicht ungültig, aber es gibt ein potenziell heikles Implementierungsdetail beim Verschachteln in Auswahllisten, insbesondere in solchen, die eine ID-Auswahl enthalten.

Damit die Verschachtelung funktioniert, wird jede Auswahlliste, die nicht die innerste Verschachtelung ist, vom Browser in :is() eingehüllt. Durch diesen Umbruch wird die Gruppierung der Auswahlliste in allen erstellten Kontexten beibehalten. Die Nebenwirkung dieser Gruppierung, :is(.one, #two), besteht darin, dass die Spezifität der höchsten Punktzahl innerhalb der Selektoren in den Klammern übernommen wird. So funktioniert :is() immer. Bei Verwendung der Verschachtelungssyntax kann das jedoch eine Überraschung sein, da es nicht genau dem entspricht, was erstellt wurde. Zusammenfassend lässt sich sagen: Verschachtelungen mit IDs und Auswahllisten können zu sehr spezifischen Auswahlkriterien führen.

Um das knifflige Beispiel noch einmal zusammenzufassen: Der vorherige Verschachtelungsblock wird auf das Dokument so angewendet:

:is(.one, #two) .three {
  /* some styles */
}

Achten Sie darauf oder weisen Sie Ihre Linter an, zu warnen, wenn Sie eine Auswahlliste mit einer ID-Auswahl verschachteln. Die Spezifität aller Verschachtelungen in dieser Auswahlliste ist dann hoch.

Verschachtelung und Deklarationen kombinieren

Betrachten Sie den folgenden verschachtelten CSS-Block:

.card {
  color: green;
  & { color: blue; }
  color: red;
}

Die Farbe der .card-Elemente ist blue.

Alle vermischten Stildeklarationen werden an den Anfang verschoben, als wären sie vor dem Verschachtelungsprozess geschrieben worden. Weitere Informationen finden Sie in der Spezifikation.

Es gibt aber Möglichkeiten, das Problem zu umgehen. Im Folgenden werden die drei Farbstile in & eingehüllt, wodurch die Kaskadenreihenfolge beibehalten wird, wie es der Autor möglicherweise beabsichtigt hat. .card-Elemente sind rot.

.card {
  color: green;
  & { color: blue; }
  & { color: red; }
}

Es empfiehlt sich sogar, alle Stile, die nach dem Verschachtelungsprozess folgen, in & einzufügen.

.card {
  color: green;

  @media (prefers-color-scheme: dark) {
    color: lightgreen;
  }

  & {
    aspect-ratio: 4/3;
  }
}

Funktionserkennung

Es gibt zwei gute Möglichkeiten, CSS-Verschachtelungen zu erkennen: Sie können Verschachtelungen verwenden oder @supports verwenden, um zu prüfen, ob die Auswahlmöglichkeit für Verschachtelungen geparst werden kann.

Ein Screenshot der Codepen-Demo von Bramus, in der gefragt wird, ob Ihr Browser CSS-Verschachtelung unterstützt. Unter dieser Frage befindet sich ein grünes Feld, das Unterstützung signalisiert.

Vorteile von Verschachtelungen:

html {
  .has-nesting {
    display: block;
  }

  .no-nesting {
    display: none;
  }
}

mit @supports:

@supports (selector(&)) {
  /* nesting parsing available */
}

Mein Kollege Bramus hat ein sehr gutes Codepen, in dem diese Strategie veranschaulicht wird.

Debugging mit Chrome-Entwicklertools

Die aktuelle Unterstützung für Verschachtelungen in den DevTools ist minimal. Derzeit werden Stile im Bereich „Stile“ wie erwartet dargestellt, aber das Verfolgen des Nestings und des vollständigen Auswahlkontexts wird noch nicht unterstützt. Wir haben ein Design und Pläne, um dies transparent und klar zu machen.

Ein Screenshot der Verschachtelungssyntax in den Chrome-Entwicklertools

In Chrome 113 soll CSS-Verschachtelung zusätzlich unterstützt werden. Bleib also dran!

Die Zukunft

CSS-Verschachtelung ist erst in Version 1 verfügbar. Version 2 wird mehr syntaktische Vereinfachungen und möglicherweise weniger Regeln enthalten, die man sich merken muss. Es gibt viele Anfragen, dass das Parsen von verschachtelten Elementen nicht eingeschränkt sein oder Probleme verursachen soll.

Das Nesting ist eine große Verbesserung der CSS-Sprache. Sie hat Auswirkungen auf fast alle architektonischen Aspekte von CSS. Diese großen Auswirkungen müssen eingehend untersucht und verstanden werden, bevor Version 2 effektiv spezifiziert werden kann.

Zum Schluss noch eine Demo, in der @scope, Verschachtelung und @layer zusammen verwendet werden. Es ist alles sehr spannend!

Eine helle Karte auf grauem Hintergrund. Die Karte enthält einen Titel und Text, einige Aktionsschaltflächen und ein Bild im Cyber-Punk-Stil.