Cascade et spécificité

CSS

On joue ?

quelle est ma couleur ?

spécificité des sélecteurs CSS

plus c'est haut, plus c'est violent

opérateurs (* > + ~ espace)
éléments (+ pseudo-éléments)
.class (+ pseudo-classes) + attribut
#id
style=""
!important
:not()
:where()
:has()

Pas d'ID en CSS !

Project Wallace

!important + specificity + nesting

Fil rouge

La Cascade CSS

!important, transitions, animations

styles navigateur, styles utilisateur, styles du développeur

règles de spécificité (poids) des sélecteurs

ordre d'affichage (le dernier écrase le précédent)

La spécificité des sélecteurs :

  1. Chaque type de sélecteur CSS a sa propre spécificité (élément, classe, id, etc.)
  2. Ajouter du poids pour écraser un sélecteur a un effet "boule de neige" pour la prochaine modification à opérer
  3. Pourquoi ce ☠️ 🤬 😡 de bouton ne devient pas hotpink ?!?!
a { color: salmon }
a:hover, a:focus { color: purple }

quelle couleur l'emporte ?

reset.css

ul#navigation > a { color: salmon }
ul#navigation li a { color: pink } /* TODO: à changer ASAP ! */
#navigation a.link { color: olive }
body ul#navigation li a { color: tomato }
body nav ul li a.link:first-child { color: chocolate }

legacy-2010.css

ul#navigation li a { color: hotpink }

navigation.css

Le problème de la spécificité

c'était "olive"

Alors on fait quoi ?

On utilise le bazooka !important

spoiler : non

.navigation-link { color: pink }
.navigation-link:first-child { color: chocolate }

legacy-2010.css

.navigation-link { color: hotpink !important }

navigation.css

!important surclasse tous les poids de sélecteurs et complique la maintenance future des styles.

bootstrap.min.css (1043x !important)

On réduit le poids dès le départ

.navigation-link { color: pink }
.navigation-link:first-child { color: chocolate }

legacy-2010.css

.navigation-link { color: hotpink }

navigation.css

Cibler uniquement avec des classes permet de modifier facilement quand le contexte change

ouais enfin quand c'est possible hein

On utilise le sélecteur :where()

wait, what?

:where()

confère une spécificité de zéro !

spécificité = 1, 1, 1

...
#navigation a.link { color: olive }
...

legacy-2010.css

ul#navigation li a { color: hotpink }

navigation.css

spécificité = 1, 0, 3 😥

spécificité = 1, 0, 0

...
#navigation :where(a.link) { color: olive }
...

legacy-2010.css

ul#navigation li a { color: hotpink }

navigation.css

spécificité = 1, 0, 3 💪

On isole avec les Cascade Layers

wait, what encore?

@layer

isole les couches de spécificités de CSS

...
#navigation a.link { color: olive }
...

legacy-2010.css

ul#navigation li a { color: hotpink }

navigation.css

je gagne

je gagne

legacy-2010.css

je place les styles dans une couche que j'appelle "legacy"

@layer legacy {
  #navigation a.link { color: olive }
}
.link { color: hotpink }

navigation.css

les styles hors layers sont prioritaires 💪

@layer

importer dans un layer

On peut importer des feuilles de styles au sein de Layers
(oui oui, ça marche avec bootstrap.css aussi)

@import "legacy-2010.css" layer(legacy);

.link { color: hotpink }

styles.css

je gagne

je gagne

On peut même importer des feuilles de styles au sein de Layers anonymes

@import "legacy-2010.css" layer;

.link { color: hotpink }

styles.css

@layer

l'ordre des couches

styles.css

/* L'ordre des layers définit la priorité des styles */

/* Chaque layer écrase le précédent si conflit */
@layer config, base, components, utilities;

/* Config */
@import "reset.css" layer(config);
@import "theme.css" layer(config);
@import "theme-tokens.css" layer(config);
@import "layouts.css" layer(config);
@import "natives.css" layer(config);

/* Base */
@import "styles.css" layer(base);

/* Components */

/* Ici un @import dans le layer(components) */

/* Utilities */

/* Ici un @import dans le layer(utilities) */

Exercice !

Cascade