Cascading Layers (die @layer
-CSS-Regel) werden in Chromium 99, Firefox 97 und Safari 15.4 Beta eingeführt. Sie ermöglichen eine explizitere Steuerung Ihrer CSS-Dateien, um Stilkonflikte zu vermeiden. Das ist besonders nützlich für große Codebases, Designsysteme und beim Verwalten von Drittanbieterstilen in Anwendungen.
Wenn Sie Ihr CSS auf klare Weise überlagern, werden unerwartete Stilüberschreibungen verhindert und die CSS-Architektur wird verbessert.
CSS-Spezifizität und die Kaskade
Anhand der CSS-Spezifität wird in CSS entschieden, welche Stile auf welche Elemente angewendet werden. Die verschiedenen Auswahlmöglichkeiten bestimmen die Spezifität einer Stilregel. Elemente sind beispielsweise weniger spezifisch als Klassen oder Attribute, die wiederum weniger spezifisch als IDs sind. Dies ist ein grundlegender Bestandteil des Erlernens von CSS.
CSS-Namenskonventionen wie BEM sollen verhindern, dass die Spezifität versehentlich überschrieben wird. Wenn Sie allen Elementen dieselbe Klassenbezeichnung geben, werden sie auf derselben Ebene der Spezifität platziert. Es ist jedoch nicht immer möglich, solche organisierten Stile beizubehalten, insbesondere wenn Sie mit Code und Designsystemen von Drittanbietern arbeiten.
Mit Kaskadebenen soll dieses Problem gelöst werden. Sie fügen der CSS-Kaskade eine neue Ebene hinzu. Bei mehrschichtigen Stilen hat die Priorität einer Ebene immer Vorrang vor der Spezifität eines Selektors.
Beispielsweise ist der Selektor .post a.link
spezifischer als .card a
. Wenn Sie versuchen, einen Link in einer Karte in einem Beitrag zu formatieren, wird die spezifischere Auswahl angewendet.
Mit @layer
können Sie die Stilspezifität der einzelnen Elemente genauer definieren und dafür sorgen, dass die Stile des Kartenlinks die Stile des Beitragslinks überschreiben, auch wenn die Spezifität numerisch niedriger sein kann, wenn sich alle CSS-Elemente auf derselben Ebene befinden. Das liegt an der Kaskadenpräferenz. Mit mehrschichtigen Stilen werden neue kaskadierende Ebenen erstellt.
@layer
in Aktion
In diesem Beispiel wird die Leistungsfähigkeit von Kaskadenebenen mit @layer
veranschaulicht. Es werden mehrere Links angezeigt: einige ohne zusätzliche Klassennamen, einer mit einer .link
-Klasse und einer mit einer .pink
-Klasse. Das CSS fügt dann drei Ebenen hinzu: base
, typography
und utilities
:
@layer base {
a {
font-weight: 800;
color: red; /* ignored */
}
.link {
color: blue; /* ignored */
}
}
@layer typography {
a {
color: green; /* styles *all* links */
}
}
@layer utilities {
.pink {
color: hotpink; /* styles *all* .pink's */
}
}
Letztendlich sind alle Verbindungen entweder grün oder rosa. Das liegt daran, dass .link
zwar eine höhere Spezifität auf Auswahlebene als a
hat, aber für a
ein Farbstil in @layer
mit höherer Priorität festgelegt ist. a { color: green }
überschreibt .link { color: blue }
, wenn sich die grüne Regel in einer Ebene nach der blauen Regel befindet.
Die Ebenenpriorität hat Vorrang vor der Elementspezifizität.
Ebenen organisieren
Sie können Ebenen wie oben gezeigt direkt auf der Seite oder oben in einer Datei organisieren.
Die Ebenenreihenfolge wird festgelegt, wenn der Name einer Ebene zum ersten Mal in Ihrem Code erscheint.
Wenn Sie also oben in der Datei Folgendes hinzufügen, werden alle Links rot und der Link mit der Klasse .link
blau angezeigt:
@layer utilities, typography, base;
Das liegt daran, dass die Ebenenreihenfolge jetzt umgekehrt ist, d. h., dass Versorgungseinrichtungen zuerst und die Basisebene zuletzt angezeigt werden. Daher haben die Stilregeln in der base
-Ebene immer eine höhere Spezifität als die Stilregeln in der Typografieebene. Sie sind dann nicht mehr grün, sondern rot oder blau.
Importe organisieren
@layer
kann auch in Importdateien verwendet werden. Sie können dies direkt beim Importieren von Stilen mit einer layer()
-Funktion tun, wie im folgenden Beispiel gezeigt:
/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */
/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */
/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */
Das obige Code-Snippet hat drei Ebenen: base
, layouts
und components
. Die Dateien „normalize“, „theme“ und „typography“ in base
, eine post
-Datei in layouts
sowie cards
und footer
in components
. Beim Importieren der Datei werden die Ebenen mithilfe der Ebenenfunktion instanziiert. Alternativ können Sie die Ebenen oben in der Datei anordnen und sie vor allen Importen deklarieren:
@layer base,
theme,
layouts,
components,
utilities;
Die Reihenfolge, in der Sie Ihre Stile @import
, spielt für die Ebenenreihenfolge keine Rolle, da sie bereits bei der ersten Instanz des Ebenennamens festgelegt wird. Das ist schon mal eine Sache weniger, um die Sie sich Gedanken machen müssen. Sie können importierte Dateien weiterhin auf bestimmte Ebenen legen, die Reihenfolge ist jedoch bereits festgelegt.
Ebenen und die Kaskade
Sehen wir uns an, wo Ebenen im Zusammenhang mit der gesamten Kaskade verwendet werden:
Die Rangfolge ist folgende:
- User-Agent normal (niedrigste Priorität)
- Lokaler Nutzer @Ebene
- Lokaler Nutzer (normal)
- Autor: @layers
- Autor normal
- Autor !important
- Autor @layer !important
- Lokaler Nutzer !important
- User-Agent !important** (höchste Priorität)
Hier sehen Sie, dass die Stile von @layer !important
umgekehrt sind. Sie sind nicht weniger spezifisch als nicht mehrschichtige (normale) Stile, sondern haben einen höheren Vorrang. Das liegt daran, wie !important
in der Kaskade funktioniert: Es unterbricht die normale Kaskade in Ihren Stylesheets und kehrt die normale Spezifität auf Ebene der Ebenen (Vorrang) um.
Verschachtelte Ebenen
Ebenen können auch in anderen Ebenen verschachtelt sein. Das folgende Beispiel stammt aus der Erläuterung zu Kaskadenebenen von Miriam Suzanne:
@layer default {
p { max-width: 70ch; }
}
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
p { margin-bottom: 1em; }
}
Im obigen Code-Snippet können Sie über ein .
auf framework.default
zugreifen, um anzugeben, dass die default
-Ebene in framework
verschachtelt ist. Sie können dies auch in einer kürzeren Schreibweise schreiben:
@layer framework.default {
p { margin-block: 0.75em }
}
Die resultierenden Ebenen und die Ebenenfolge sind:
- Standard
framework.default
framework
ohne Ebenen- ohne Ebenen
Was Sie beachten sollten
Wenn Sie sie richtig verwenden, können sie sehr hilfreich sein. Sie können aber auch zu Verwirrung und unerwarteten Ergebnissen führen. Beachten Sie bei der Arbeit mit Kaskadenebenen Folgendes:
Regel 1: Verwenden Sie @layer
nicht für den Geltungsbereich
Mit Kaskadenebenen lässt sich das Problem nicht lösen. Wenn Sie eine CSS-Datei mit einer @layer
haben, z. B. card.css
, und alle Links auf der Karte formatieren möchten, sollten Sie keine Stile wie die folgenden schreiben:
a {
…
}
Dadurch wird diese Überschreibung auf alle a
-Tags in Ihrer Datei angewendet. Es ist jedoch wichtig, die Umfang Ihrer Stile richtig zu definieren:
.card a {
…
}
Regel 2: Cascading-Ebenen werden hinter nicht geschichtetem CSS angeordnet.
Eine mehrschichtige CSS-Datei überschreibt nicht das nicht mehrschichtige CSS. Diese Entscheidung wurde bewusst getroffen, um die Einführung von Ebenen zu vereinfachen und die Arbeit mit Ihrer vorhandenen Codebasis sinnvoller zu gestalten. Die Verwendung einer reset.css
-Datei ist ein guter Ausgangspunkt und Anwendungsfall für kaskadierte Ebenen.
Regel 3: !important
invertiert die Spezifität der Kaskade
Ebenenstilen sind im Allgemeinen weniger spezifisch als Stilelemente ohne Ebenen. Mit !important
wird dies umgekehrt. In einer Schicht sind Deklarationen mit der !important
-Regel spezifischer als nicht geschichtete Stile.
In diesem Fall wird die Spezifität der !important
-Stile umgekehrt. Das Diagramm oben zeigt dies zur Veranschaulichung: „author @layers“ hat eine niedrigere Priorität als „author normal“, das wiederum eine niedrigere Priorität als „author !important“ hat, das wiederum eine niedrigere Priorität als „author @layer !important“ hat.
Wenn Sie mehrere Ebenen haben, hat die erste Ebene mit !important
Vorrang und ist der spezifischeste Stil.!important
Regel 4: Einfügepunkte verstehen
Da die Ebenenreihenfolge festgelegt wird, wenn jeder Ebenenname zum ersten Mal in Ihrem Code erscheint, wird eine @layer
-Deklaration, die nach dem Importieren und Festlegen von layer()
-Werten oder nach einer anderen @layer
-Anweisung eingefügt wird, möglicherweise ignoriert. Im Gegensatz zu CSS, wo die Stilregel, die sich am weitesten unten auf der Seite befindet, für die Kaskadenebenen angewendet wird, wird die Reihenfolge in erster Instanz festgelegt.
Dies kann in einer Liste, in einem Ebenenblock oder in einem Import erfolgen. Wenn Sie @layer
nach einer Importliste mit layer()
einfügen, passiert nichts. Wenn Sie sie oben in der Datei platzieren, wird die Ebenenreihenfolge festgelegt und Sie können die Ebenen in der Architektur besser sehen.
Regel 5: Achten Sie auf Spezifität
Bei kaskadierenden Ebenen überschreibt ein weniger spezifischer Selector (z. B. a
) einen spezifischeren Selector (z. B. .link
), wenn sich dieser weniger spezifische Selector auf einer spezifischeren Ebene befindet. Hier einige Tipps:
a
in layer(components)
überschreibt .pink
in layer(utilities)
, wenn: @layer utilities, components
angegeben wurde. Das ist zwar ein beabsichtigter Teil der API, kann aber verwirrend und frustrierend sein, wenn Sie es nicht erwarten.
Wenn Sie also Dienstprogrammklassen schreiben, sollten Sie sie immer in einer höheren Schicht anordnen als die Komponenten, mit denen Sie sie überschreiben möchten. Vielleicht denken Sie: „Ich habe gerade diese .pink
-Klasse hinzugefügt, um die Farbe zu ändern, aber sie wird nicht angewendet.“
Weitere Informationen zu Kaskadenebenen
Weitere Informationen zu Kaskadenebenen finden Sie in den folgenden Ressourcen: