CSS Cascade Layers – Kaskadenebenen statt Spezifität
CSS Cascade Layers vereinfachen den Umgang mit CSS Spezifität, indem sie den Code in separaten Ebenen mit klar zugewiesener Priorität organisieren.
Die Kontrolle der CSS Spezifität ist eine der größeren Herausforderungen, auf die wir beim Schreiben von CSS-Code stoßen können. Obwohl die Spezifität eine wichtige CSS-Grundlage ist, bemerken wir häufig, dass sie nicht ausreichend bekannt ist, oder wird durch Frameworks etc. verkompliziert wird. Das Resultat sind unnötig komplizierte Selektoren und unübersichtliche Verschachtelungstiefen, die sich so weit aufschaukeln, bis mit !important
& Co. zu weit gegangen wird. Damit ist dann – Inline CSS einmal außer Acht gelassen – das Ende der Fahnenstange erreicht. Der Code, der entsteht, ist schwer zu pflegen, zu erweitern und fehleranfällig.
CSS Cascade Layers bieten eine Lösung für genau dieses Problem. Wir geben einen Überblick darüber, wie diese funktionieren und wie sie Spezifitäts-Probleme lösen können.
Nachteile beim CSS-Styling mit Hilfe von Spezifitäten
Um euch den Unterschied bzw. die Vorteile von CSS Cascade Layers gegenüber Spezifitäten bzw. Verschachtelungen im CSS-Code zu zeigen, verwenden wir ein einfaches Beispiel: Eine Liste mit individuellem Styling.
Wir verwenden folgenden Code, um das Standard-Styling des Browsers für Listen zurückzusetzen, sobald diese eine Klasse erhalten haben.
ul[class] {
padding: 0;
list-style: none;
}
Nun erstellen wir eine Liste mit der Klasse .highlight
, um das gewünschte Styling auf die Liste anzuwenden. Durch das Hinzufügen der Klasse im HTML wird die Liste von unserem vorher geschriebenen Listen-Reset beeinflusst und das Padding sowie der Listen-Style werden wie gewünscht entfernt.
<div class="site-main">
<ul class="highlight">
<li>Listenpunkt</li>
<li>Listenpunkt</li>
<li>Listenpunkt</li>
<li>Listenpunkt</li>
</ul>
</div>
Wenn wir unserer Highlight-Liste (.highlight
, 10 Punkte) nun wieder ein Padding und ein Listen-Styling zuweisen möchten, müssen wir allerdings aufgrund der hohen Spezifität von ul[class]
(11 Punkte) anfangen, die Selektoren zu kombinieren und z.B. so etwas schreiben wie .site-main .highlight
(20 Punkte), damit das Styling angewendet wird.
ul[class] {
padding: 0;
list-style: none;
}
.site-main .highlight {
padding: 2rem;
list-style: square;
}
CSS Cascade Layers statt Verschachtelung
Mit CSS Cascade Layers können wir das Verschachteln von Klassen, IDs, etc. für eine höhere Spezifität umgehen, indem wir den Listen-Reset einer eigenen Ebene (Layer) zuweisen. Die Zuweisung erfolgt über die Regel @layer
. Wir definieren einen Layer mit dem Namen reset
und weisen unseren Listen-Reset diesem Layer zu.
Styles, die außerhalb eines Layers definiert sind, haben immer eine höhere Priorität.
Folglich benötigen wir keinen kombinierten Selektor mehr, um die im Layer reset
definierten Styles zu überschreiben.
@layer reset {
ul[class] {
padding: 0;
list-style: none;
}
}
.highlight {
padding: 2rem;
list-style: square;
}
Priorität von verschiedenen Layern festlegen
Die Priorität der Layer zueinander wird über die Reihenfolge bestimmt. Wenn wir in einem großen Team und/oder einem komplexen System arbeiten, das verschiedene Stylesheets lädt, kann es sein, dass wir nicht die volle Kontrolle über die Reihenfolge haben.
Hierfür bieten CSS Cascade Layers es eine einfache Lösung, die am Anfang des CSS-Baums definiert werden muss. Im folgenden Beispiel hat der Layer reset
die kleinste Priorität und components
die höchste, unabhängig davon in welcher Reihenfolge die Layer im darunterliegenden Code angeordnet sind.
/* Wir definieren drei Layers mit aufsteigender Priorität */
@layer reset, utilities, components;
@layer utilities {
/* Angaben haben Priorität 2 und überschreiben Angaben aus dem layer reset */
ul[class^="list"] {
padding: 2rem;
list-style: disc;
}
}
@layer components {
/* Angaben haben Priorität 3 und überschreiben Angaben aus den layer reset und utilities */
.list-highlight {
padding: 3rem;
list-style: square;
}
}
@layer reset {
/* Angaben haben Priorität 1 und werden von Angaben aus allen layern überschrieben */
ul[class] {
padding: 0;
list-style: none;
}
}
Verschachteln von Layern (nesting)
CSS Cascade Layers können ineinander verschachtelt werden. Im Beispiel gehen wir davon aus, dass wir zwei verschiedenen Frameworks laden, die in sich mit gleich benannten Layern arbeiten. Pro Framework wird ein eigenständiger Eltern-Layer verwendet.
@layer framework1, framework2;
@layer framework1 {
@layer globals {
...
}
@layer colors {
...
}
}
@layer framework2 {
@layer globals {
...
}
@layer colors {
...
}
}
Um auf einen Kind-Layer in einem verschachtelten Layer direkt zugreifen zu können, können wir nun mit sogenannten gruppierten Layern arbeiten. Werden die Namen des Eltern- und Kind-Layers mit einem .
verknüpft, kann auch außerhalb des Eltern-Layers auf den Kind-Layer zugegriffen werden. Das ist z. B. sinnvoll, wenn wir den Code unseres Frameworks nicht verändern wollen oder können, um beispielsweise updatefähig zu bleiben.
@layer framework1.globals {
...
}
@layer framework2.colors {
...
}
Ganze Stylesheets mit @import
einem Layer zuweisen
Auch ganze Stylesheet-Dateien, die über @import
importiert werden, können einem speziellen Layer zugeordnet werden. Hierfür müsst wir nach der url
-Angabe layer(<layer-name>)
schreiben.
@import url('normalize.css') layer(reset);
CSS Cascade Layers für Standard-Browser-Styles
Eigentlich sind CSS Cascade Layers nichts Neues. Beispielsweise ist der Standard-Browser-Style auch in seinem eigenen Layer gekapselt. Aber jetzt steht auch uns in der Frontend-Entwicklung dieses mächtige Werkzeug zur Kontrolle der Kaskaden zur Verfügung.
Browser Support
Den detaillierten Browser-Support für dieses Feature könnt ihr auf caniuse.com einsehen.