CSS-Verschachtelung

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

Adam Argyle
Adam Argyle

Vor der Verschachtelung 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;
    }
  }
}

Im Browser ausprobieren

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 Stile so besser an das HTML angepasst werden, auf das 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

Verschachtelungen sind ab Chrome 112 verfügbar und können auch in der Safari-Technischen Vorschau 162 getestet werden.

Erste Schritte mit der Verschachtelung von Preisvergleichsportalen

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 der verschachtelte .child-Selektor nur auf Elemente angewendet wird, die untergeordnete Elemente von Elementen mit einer .parent-Klasse sind.

Dieses Beispiel könnte alternativ mit dem Symbol & geschrieben werden, um explizit 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 Verschachtelung 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);
  }
}

Das Ergebnis: Alle Elemente innerhalb von .demo mit einer .circle-Klasse sind unkenntlich gemacht und fast unsichtbar:

Das bunte Raster der Formen hat keine Kreise mehr,
    sie sind im Hintergrund sehr schwach.
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 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:

Das farbige Raster der Formen enthält nur Kreise, alle anderen Formen sind nahezu 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 gilt für CSS derzeit Folgendes:

.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);
    }
  }
}

Das Ergebnis, alle großen Dreiecke und Kreise sind in .demo ausgeblendet:

Im farbenfrohen 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 Pseudoklasse für die Negationsfunktion 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. Hierfür ist & erforderlich:

.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 zum Verschachteln enthält viele 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-Abschnitte verschachteln

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 geht durch die Möglichkeit, die Bedingungen direkt im Kontext zu verschachteln.

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

Überall verschachtelt

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 Szenarien für die Verschachtelungssyntax, die ungültig sind und Sie möglicherweise überraschen, wenn Sie in Präprozessoren 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. Das 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. In diesem Verschachtelungsbeispiel gibt es nichts ungültiges, aber es gibt ein möglicherweise kompliziertes Implementierungsdetail bei der Verschachtelung in Selektorlisten, insbesondere in solchen, die einen ID-Selektor enthalten.

Damit die Verschachtelung funktioniert, wird jede Selektorliste, die nicht die innerste Verschachtelung ist, vom Browser mit :is() umschlossen. Durch diesen Umbruch wird die Gruppierung der Auswahlliste in allen erstellten Kontexten beibehalten. Der Nebeneffekt dieser Gruppierung, :is(.one, #two), besteht darin, dass sie die Spezifität der höchsten Punktzahl innerhalb der Selektoren innerhalb der Klammern übernimmt. So funktioniert :is() immer. Bei Verwendung der Verschachtelungssyntax kann das jedoch überraschend 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 schwierige Beispiel kurz zusammenzufassen, wird der vorherige Verschachtelungsblock so auf das Dokument angewendet:

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

Achten Sie darauf oder legen Sie fest, dass Ihre Linter 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 von .card-Elementen ist blue.

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

Es gibt aber Möglichkeiten, das Problem zu umgehen. Im Folgenden werden die drei Farbstile in & umschlossen, wodurch die Kaskadenreihenfolge wie vom Autor beabsichtigt beibehalten wird. .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 mit @supports 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 auf Unterstützung hinweist.

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.

Fehlerbehebung mit den Chrome-Entwicklertools

Die aktuelle Unterstützung für Verschachtelungen in 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. Das Parsen von Verschachtelungen ist gefragt, um nicht begrenzt zu sein oder schwierige Momente zu haben.

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 hat einen Titel und Text, einige Aktionsschaltflächen und ein Bild im Cyber-Punk-Stil.