Les calques en cascade (la règle CSS @layer
) seront disponibles dans Chromium 99, Firefox 97 et Safari 15.4 Bêta. Ils permettent de contrôler plus explicitement vos fichiers CSS afin d'éviter les conflits de spécificité de style. Cela est particulièrement utile pour les grands codebases, les systèmes de conception et la gestion des styles tiers dans les applications.
En stratifiant votre CSS de manière claire, vous évitez les remplacements de style inattendus et améliorez l'architecture CSS.
Spécificité CSS et cascade
La spécificité CSS permet au CSS de déterminer les styles à appliquer aux éléments. Les différents sélecteurs que vous pouvez utiliser déterminent la spécificité de chaque règle de style. Par exemple, les éléments sont moins spécifiques que les classes ou les attributs, qui sont à leur tour moins spécifiques que les ID. Il s'agit d'une partie essentielle de l'apprentissage du CSS.
Les concepteurs se tournent vers des conventions d'attribution de noms CSS telles que BEM pour éviter de remplacer la spécificité par inadvertance. En attribuant un seul nom de classe à tous les éléments, vous les placez tous sur le même plan de spécificité. Cependant, il n'est pas toujours possible de maintenir des styles aussi organisés, en particulier lorsque vous travaillez avec du code et des systèmes de conception tiers.
Les couches en cascade visent à résoudre ce problème. Ils introduisent une nouvelle couche dans la cascade CSS. Avec les styles en couches, la priorité d'une couche l'emporte toujours sur la spécificité d'un sélecteur.
Par exemple, le sélecteur .post a.link
est plus spécifique que .card a
. Si vous essayez de styliser un lien dans une fiche d'un post, le sélecteur le plus spécifique sera appliqué.
En utilisant @layer
, vous pouvez être plus explicite sur la spécificité de style de chacun et vous assurer que les styles de votre lien de carte remplacent les styles de votre lien de post, même si la spécificité peut être numériquement inférieure si tous vos CSS se trouvent sur le même plan. Cela est dû à la priorité en cascade. Les styles en couches créent de nouveaux "plans" en cascade.
@layer
en action
Cet exemple illustre la puissance des calques en cascade à l'aide de @layer
. Plusieurs liens s'affichent: certains sans nom de classe supplémentaire, un avec une classe .link
et un avec une classe .pink
. Le CSS ajoute ensuite trois couches: base
, typography
et utilities
, comme suit:
@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 */
}
}
À terme, tous les liens sont verts ou roses. En effet, bien que .link
ait une spécificité au niveau du sélecteur plus élevée que a
, il existe un style de couleur sur a
dans un @layer
de priorité supérieure. a { color: green }
remplace .link { color: blue }
lorsque la règle verte se trouve dans un calque après la règle bleue.
La priorité des calques l'emporte sur la spécificité des éléments.
Organiser les calques
Vous pouvez organiser les calques directement sur la page, comme indiqué ci-dessus, ou en haut d'un fichier.
L'ordre des calques est établi la première fois que chaque nom de calque apparaît dans votre code.
Cela signifie que si vous ajoutez ce qui suit en haut du fichier, les liens s'afficheront tous en rouge, et le lien de la classe .link
en bleu:
@layer utilities, typography, base;
En effet, l'ordre des calques est désormais inversé, les éléments utilitaires étant placés en premier et la base en dernier. Par conséquent, les règles de style de la couche base
auront toujours une spécificité plus élevée que les règles de style de la couche de typographie. Ils ne seront plus verts, mais rouges ou bleus.
Organiser les importations
Vous pouvez également utiliser @layer
avec des fichiers d'importation. Vous pouvez le faire directement lorsque vous importez des styles, à l'aide d'une fonction layer()
, comme dans l'exemple suivant :
/* 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 */
L'extrait de code ci-dessus comporte trois couches: base
, layouts
et components
. Les fichiers de normalisation, de thème et de typographie dans base
, avec un fichier post
dans layouts
, et cards
et footer
dans components
. Lors de l'importation du fichier, les calques sont instanciés à l'aide de la fonction de calque. Vous pouvez également organiser vos calques en haut du fichier, en les déclarant avant toute importation:
@layer base,
theme,
layouts,
components,
utilities;
Désormais, l'ordre dans lequel vous @import
vos styles n'a plus d'importance pour l'ordre des calques, car il est déjà établi à la première occurrence du nom du calque. Un souci de moins. Vous pouvez toujours définir des fichiers importés sur des calques spécifiques, mais l'ordre est déjà établi.
Couches et cascade
Prenons un peu de recul et voyons où les couches sont utilisées par rapport à la cascade plus large:
L'ordre de priorité est le suivant:
- User-agent normal (priorité la plus faible)
- Utilisateur local @couche
- Utilisateur local normal
- Auteur @layers
- Auteur normal
- Auteur !important
- Auteur @layer !important
- Utilisateur local !important
- User-agent !important** (priorité la plus élevée)
Vous remarquerez ici que les styles @layer !important
sont inversés. Au lieu d'être moins spécifiques que les styles non superposés (normaux), ils ont une priorité plus élevée. Cela s'explique par le fonctionnement de !important
dans la cascade: il interrompt la cascade normale dans vos feuilles de style et inverse la spécificité normale au niveau de la couche (préséance).
Calques imbriqués
Les calques peuvent également être imbriqués dans d'autres calques. L'exemple suivant provient de la présentation des calques en cascade de Miriam Suzanne:
@layer default {
p { max-width: 70ch; }
}
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
p { margin-bottom: 1em; }
}
Dans l'extrait de code ci-dessus, vous pouvez accéder à framework.default
à l'aide d'un .
pour indiquer que la couche default
est imbriquée dans framework
. Vous pouvez également écrire cela de manière plus abrégée:
@layer framework.default {
p { margin-block: 0.75em }
}
Les calques et l'ordre des calques obtenus sont les suivants:
- par défaut
framework.default
framework
sans calque- sans superposition
Points à noter
Les calques en cascade peuvent être très utiles si vous les utilisez correctement, mais ils peuvent aussi créer de la confusion et des résultats inattendus. Tenez compte des points suivants lorsque vous utilisez des calques en cascade:
Règle 1: N'utilisez pas @layer
pour définir le champ d'application
Les calques en cascade ne résolvent pas le problème de champ d'application. Si vous disposez d'un fichier CSS avec un @layer
, par exemple card.css
, et que vous souhaitez styliser tous les liens de la fiche, n'écrivez pas de styles comme:
a {
…
}
Toutes les balises a
de votre fichier recevront ce forçage. Il est néanmoins important de définir correctement la portée de vos styles:
.card a {
…
}
Règle 2: les couches en cascade sont triées derrière les CSS non stratifiés
Notez qu'un fichier CSS en couches ne remplace pas le CSS non en couches. Il s'agit d'une décision délibérée visant à faciliter l'introduction de calques de manière plus judicieuse pour travailler avec votre codebase existant. L'utilisation d'un fichier reset.css
, par exemple, constitue un bon point de départ et un bon cas d'utilisation pour les calques en cascade.
Règle 3: !important
inverse la spécificité de la cascade
Bien que les styles en couches soient généralement moins spécifiques que les styles sans couches, l'utilisation de !important
inverse cette tendance. Dans une couche, les déclarations avec la règle !important
sont plus spécifiques que les styles sans couche.
Dans ce cas, les styles !important
inversent leur spécificité. Le diagramme ci-dessus le montre à titre de référence: les attributs author @layers ont moins de priorité que les attributs author normal, qui ont moins de priorité que les attributs author !important, qui ont moins de priorité que les attributs author @layer !important.
Si vous avez plusieurs calques, le premier calque avec !important
sera prioritaire et sera le style le plus spécifique.!important
Règle 4: Comprendre les points d'injection
Étant donné que l'ordre des calques est établi la première fois que chaque nom de calque apparaît dans votre code, si vous placez une déclaration @layer
après avoir importé et défini des layer()
, ou après une autre instruction @layer
, elle peut être ignorée. Contrairement au CSS, où la règle de style la plus basse de la page est appliquée pour les couches en cascade, l'ordre est établi à la première instance.
Il peut s'agir d'une liste, d'un bloc de calques ou d'une importation. Si vous placez @layer
après une liste d'importation avec layer()
, rien ne se passe. En le plaçant en haut du fichier, vous définirez l'ordre des calques et vous pourrez voir clairement les calques dans l'architecture.
Règle 5: Faites attention à votre niveau de spécificité
Avec les calques en cascade, un sélecteur moins spécifique (comme a
) remplace un sélecteur plus spécifique (comme .link
) si ce sélecteur moins spécifique se trouve sur un calque plus spécifique. Réfléchissez aux éléments suivants :
a
dans layer(components)
remplace .pink
dans layer(utilities)
si: @layer utilities, components
a été spécifié. Bien que cela soit intentionnel dans l'API, cela peut être déroutant et frustrant si vous ne vous y attendez pas.
Par conséquent, si vous écrivez des classes utilitaires, incluez-les toujours en tant que couche de niveau supérieur que les composants que vous prévoyez de remplacer. Vous pourriez penser : "Je viens d'ajouter cette classe .pink
pour modifier la couleur, mais elle n'est pas appliquée."
En savoir plus sur les calques en cascade
Vous pouvez également consulter ces ressources pour en savoir plus sur les calques en cascade: