In Ihrem Browser kommen Kaskadierungsebenen

Cascade Layer (die CSS-Regel @layer) sind in der Betaversion von Chromium 99, Firefox 97 und Safari 15.4 verfügbar. Sie ermöglichen eine explizitere Kontrolle über Ihre CSS-Dateien, um Konflikte bei Stilspezifikationen zu vermeiden. Dies ist besonders nützlich bei großen Codebasen, Designsystemen und bei der Verwaltung von Drittanbieter-Stilen in Anwendungen.

Eine klare Überlagerung Ihres CSS-Codes verhindert unerwartete Stilüberschreibungen und fördert eine bessere CSS-Architektur.

CSS-Spezifität und die Kaskade

Anhand der CSS-Spezifität entscheidet CSS, welche Stile auf welche Elemente angewendet werden. Mit den verschiedenen zur Auswahl stehenden Selektoren wird die Spezifität einer Stilregel bestimmt. Elemente sind beispielsweise weniger spezifisch als Klassen oder Attribute, die wiederum weniger spezifisch sind als IDs. Dies ist ein wesentlicher Bestandteil des CSS-Lernens.

Die Leute verwenden CSS-Namenskonventionen wie BEM, um zu verhindern, dass Spezifitäten versehentlich überschrieben werden. Indem alle Elemente einen einzigen Klassennamen erhalten, befindet sich alles auf derselben Spezifitätsebene. Es ist jedoch nicht immer möglich, solche organisierten Stile beizubehalten, insbesondere wenn Sie mit Code und Designsystemen von Drittanbietern arbeiten.

BEM-Darstellung einer Karte mit Kursen
Ein illustriertes Beispiel für die BEM-Benennung auf keepinguptodate.com.

Dieses Problem soll mit Kaskadenebenen gelöst werden. Sie fügen der CSS-Kaskade eine neue Ebene hinzu. Bei Stilen mit mehreren Ebenen hat eine Ebene immer Vorrang vor der Spezifität eines Selektors.

Der Selektor .post a.link hat beispielsweise eine höhere Spezifität als .card a. Wenn Sie versuchen, einen Link zu gestalten, werden Sie innerhalb einer Karte oder eines Beitrags feststellen, dass die spezifischere Auswahl angewendet wird.

Mit @layer können Sie die Stilspezifität der einzelnen Elemente deutlicher hervorheben und sicherstellen, dass die Stile Ihres Kartenlinks die Stile des Beitrags-Links überschreiben, auch wenn die Spezifität numerisch niedriger sein kann, wenn sich Ihr gesamtes CSS auf derselben Ebene befindet. Dies liegt an der Kaskadenpriorität. Mithilfe von Stilen mit mehreren Ebenen werden neue kaskadierende „Ebenen“ erstellt.

Illustration einer Projektdemo einer Aufschlüsselung der Benutzeroberfläche

@layer in Aktion

Demo zur Darstellung von Linkfarben mit Importen
Siehe Demo zu Codepen.

Dieses Beispiel zeigt die Leistungsfähigkeit von Kaskadenebenen mithilfe von @layer. Es werden mehrere Links angezeigt: einige ohne zusätzliche Klassennamen, einer mit einer .link-Klasse und einer mit einer .pink-Klasse. Der CSS-Code 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 Links entweder grün oder rosa. Das liegt daran: Während .link eine höhere Spezifität auf Selektorebene hat als a, gibt es bei a einen Farbstil in einer @layer mit höherer Priorität. a { color: green } überschreibt .link { color: blue }, wenn sich die grüne Regel auf einer Ebene nach der blauen Regel befindet.

Die Ebene der Ebene ist schneller als die Elementspezifität.

Ebenen organisieren

Sie können Ebenen wie oben gezeigt direkt auf der Seite oder oben in einer Datei organisieren.

Die Ebenenreihenfolge wird festgelegt, indem der jeweilige Ebenenname zum ersten Mal in Ihrem Code erscheint.

Wenn Sie also am Anfang der Datei Folgendes hinzufügen, werden alle Links rot und der Link mit der Klasse .link blau angezeigt:

@layer utilities, typography, base;

Dies liegt daran, dass die Ebenenreihenfolge jetzt umgekehrt ist, d. h. Dienstprogramme zuerst und Basis am Ende stehen. Daher sind die Stilregeln auf der base-Ebene immer spezifischer als die Stilregeln in der Typografieebene. Es sind keine grünen Links mehr, sondern rot oder blau.

Screenshot des Codepen-Projekts
Siehe Demo zu Codepen.

Importe organisieren

Eine andere Möglichkeit, @layer zu verwenden, sind Importdateien. Das ist direkt beim Importieren von Stilen möglich. Verwenden Sie dazu eine layer()-Funktion wie im folgenden Beispiel:

/* 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 Normalisierungs-, Design- und Typografiedateien in base, mit einer post-Datei in layouts und cards und footer beide in components. Beim Importieren der Datei werden die Ebenen mithilfe der Funktion „layer“ instanziiert. Ein alternativer Ansatz wäre, Ihre Ebenen am Anfang der Datei zu organisieren und sie vor dem Import zu deklarieren:

@layer base,
       theme,
       layouts,
       components,
       utilities;

Die Reihenfolge, in der Sie mit @import Ihre Stile markieren, spielt für die Ebenenreihenfolge keine Rolle, da sie bereits bei der ersten Instanz des Ebenennamens festgelegt wurde. Darüber müsst ihr euch keine Sorgen machen. Sie können importierte Dateien weiterhin auf bestimmte Ebenen festlegen, die Reihenfolge ist jedoch bereits festgelegt.

Screenshot aus dem Codepen-Projekt
Sehen Sie sich das Projekt auf Codepen an.

Ebenen und die Kaskade

Gehen wir einen Schritt zurück und sehen wir uns an, wo in Bezug auf die größere Kaskade Ebenen verwendet werden:

Kaskadenabbildung

Die Reihenfolge ist wie folgt:

  • User-Agent normal (niedrigste Rangfolge)
  • Lokaler Nutzer @layer
  • Lokaler Nutzer – normal
  • Autor: @layers
  • Autor normal
  • Autor !wichtig
  • Autor @layer !important
  • Lokaler Benutzer !wichtig
  • User-Agent !important** (höchste Priorität)

Hier sehen Sie möglicherweise, dass @layer !important-Stile umgekehrt sind. Sie sind nicht weniger spezifisch als Stile ohne Ebenen (normal), sondern haben eine höhere Priorität. Das liegt an der Funktionsweise von !important in der Kaskade: Es löst die normale Kaskadierung in Ihren Stylesheets auf und kehrt die normale Spezifität auf Ebenenebene (Priorität) um.

Verschachtelte Ebenen

Ebenen können auch in anderen Ebenen verschachtelt sein. Das folgende Beispiel stammt aus der Erklärung 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 auf framework.default zugreifen und dabei eine . als Signifikanz der default-Ebene verwenden, die in framework verschachtelt ist. Sie können dies auch in einem kürzeren Format schreiben:

@layer framework.default {
  p { margin-block: 0.75em }
}

Die resultierenden Ebenen und die Reihenfolge der Ebenen sind:

  • Standardeinstellung
  • framework.default
  • framework nicht überlagert
  • Ungeschichtet

Was Sie beachten sollten

Kaskadierende Ebenen können bei korrekter Verwendung eine tolle Sache sein, aber sie können auch zu zusätzlicher Verwirrung und unerwarteten Ergebnissen führen. Achten Sie bei der Arbeit mit Kaskadenebenen auf Folgendes:

Regel 1: @layer nicht für den Umfang festlegen

Kaskadierende Ebenen lösen keinen Gültigkeitsbereich. Wenn Sie eine CSS-Datei mit einem @layer haben, sagen Sie card.css, und Sie möchten alle Links innerhalb der Karte gestalten, schreiben Sie keine Stile wie die folgenden:

a {
  …
}

Dies führt dazu, dass alle a-Tags in Ihrer Datei diese Überschreibung erhalten. Trotzdem ist es wichtig, die Styles richtig anzupassen:

.card a {
  …
}

Regel 2: Kaskadierende Ebenen werden hinter CSS ohne Ebenen angeordnet

Dabei ist zu beachten, dass CSS-Dateien ohne Ebenen nicht überschrieben werden. Dies war eine bewusste Entscheidung, um das Einführen von Ebenen auf sinnvollere Weise zu erleichtern, um mit Ihrer vorhandenen Codebasis zu arbeiten. Die Verwendung einer reset.css-Datei ist beispielsweise ein guter Ausgangspunkt und Anwendungsfall für Kaskadenebenen.

Regel 3: !important invertiert die Kaskadenspezifität

Während überlagerte Stile im Allgemeinen weniger spezifisch sind als Stile ohne Ebenen, kehren Sie dies mit !important um. In einer Ebene sind Deklarationen mit der Regel !important spezifischer als Stile ohne Ebenen.

In diesem Fall kehren die !important-Stile ihre Spezifität um. Das obige Diagramm zeigt dies als Referenz: author @layers hat eine geringere Priorität als author normal, die wiederum eine geringere Rangfolge als author !important haben, die weniger Vorrang als author @layer !important haben.

Wenn Sie mehrere Ebenen haben, hat die erste Ebene mit !important die Priorität !important und ist der spezifischste Stil.

Regel 4: Injektionspunkte verstehen

Da die Ebenenreihenfolge festgelegt wird, wenn ein Ebenenname zum ersten Mal in Ihrem Code erscheint, kann eine @layer-Deklaration ignoriert werden, nachdem Sie layer() importiert und festgelegt haben, oder nach einer anderen @layer-Anweisung. Anders als bei CSS, wo die Stilregel am weitesten unten auf der Seite für Kaskadenebenen angewendet wird, wird die Reihenfolge zuerst festgelegt.

Dies kann in einer Liste, in einem Ebenenblock oder in einem Import erfolgen. Wenn Sie @layer nach einer Importliste mit layer() einfügen, geschieht nichts. Wenn Sie es an den Anfang der Datei stellen, wird die Ebenenreihenfolge festgelegt und Sie können die Ebenen innerhalb der Architektur klar erkennen.

Regel 5: Achten Sie auf Ihre Spezifität

Bei Kaskadenebenen überschreibt ein weniger spezifischer Selektor wie a einen spezifischeren Selektor wie .link, wenn sich dieser weniger spezifische Selektor auf einer spezifischeren Ebene befindet. Ziehen Sie Folgendes in Betracht:

a in layer(components) würde .pink in layer(utilities) überschreiben, wenn @layer utilities, components angegeben wurde. Das ist zwar beabsichtigt, kann aber verwirrend und frustrierend sein, wenn Sie nicht damit rechnen.

Wenn Sie also Dienstprogrammklassen schreiben, fügen Sie diese immer als übergeordnete Ebene ein 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

Sie können sich auch die folgenden Ressourcen ansehen, um mehr über Kaskadenebenen zu erfahren: