Spécificité
Le poids d’un sélecteur, qui détermine quelle règle gagne lorsque plusieurs règles définissent la même propriété du même élément.
Exemple
#/* (1, 0, 1) */
#menu a {
color: #a1a1aa;
}
/* (0, 1, 0) : perd, bien qu’écrite plus bas */
.active {
color: #fbbf24;
}
/* (1, 1, 1) : gagne */
#menu a.active {
font-weight: 700;
border-bottom: 2px solid #fbbf24;
}<nav id="menu" class="stage" style="display: flex; gap: 16px;">
<a href="#" style="text-decoration: none;">Cours</a>
<a href="#" class="active" style="text-decoration: none;">Documentation</a>
<a href="#" style="text-decoration: none;">Collections</a>
</nav>Le lien actif a le gras et le soulignement de la troisième règle, mais garde sa couleur grise : .active a perdu face au #menu a plus fort.
Définition et utilisation
#Quand deux règles définissent la même propriété du même élément, le navigateur doit désigner un gagnant. L’un des critères principaux est la spécificité, c’est-à-dire le poids du sélecteur, noté sous la forme de trois nombres (a, b, c) : a est le nombre d’identifiants, b le nombre de classes, d’attributs et de pseudo-classes, et c le nombre de sélecteurs de type et de pseudo-éléments.
Les poids se comparent à partir de la gauche, colonne par colonne. (1, 0, 0) l’emporte sur (0, 15, 0), car la première colonne tranche avant même qu’on regarde la seconde. Ce n’est pas une simple somme de points. Le sélecteur universel * et les combinateurs (espace, >, +, ~) n’ajoutent rien. En cas d’égalité, la règle écrite le plus tard gagne.
Les pseudo-classes fonctionnelles ont leurs propres règles. :is(), :not() et :has() reprennent le poids du sélecteur le plus fort de leur liste, tandis que :where() pèse toujours zéro, ce qui permet d’écrire des styles faciles à écraser. :nth-child(… of S) correspond au poids de la pseudo-classe plus celui du sélecteur le plus fort de S.
D’autres étapes de la cascade se situent au-dessus de la spécificité. Les styles de l’attribut style l’emportent sur tout sélecteur de la feuille de style, et une déclaration avec !important l’emporte sur les déclarations ordinaires, quel que soit le poids du sélecteur (entre plusieurs !important, c’est de nouveau la spécificité qui décide). Les couches @layer fonctionnent de façon similaire : une règle d’une couche plus tardive gagne, même avec un sélecteur plus faible.
Syntaxe
#/* spécificité = (a, b, c) */
#id /* a : (1, 0, 0) */
.classe [attribut] :hover /* b : (0, 1, 0) */
p ::before /* c : (0, 0, 1) */
* > + ~ :where() /* sans poids : (0, 0, 0) */Duels de règles
#(0, 1, 0) > (0, 0, 1)
Une classe pèse plus qu’un sélecteur de type, donc le fond est vert, même si la règlepest écrite plus bas.(1, 0, 0) > (0, 2, 0)
Un seul identifiant l’emporte sur n’importe quel nombre de classes. Le fond est bleu.(0, 1, 0) = (0, 1, 0)
Égalité. À poids égal, la règle écrite le plus tard gagne, donc le fond est vert.(0, 0, 0) < (0, 0, 1)
:where()ramène le poids à zéro, donc la règle avec l’identifiant, bien qu’écrite plus bas, perd face au simplep. Le fond est vert.(1, 0, 0) > (0, 1, 0)
:is()prend le poids du sélecteur le plus fort de la liste, même quand l’élément correspond via lepplus faible. Le fond est bleu.le poids n’a pas d’importance
!importantgagne face à une déclaration ordinaire, quel que soit le poids du sélecteur. Le fond est vert malgré l’identifiant.attribut style
Un style écrit dans l’attributstyleest plus fort que n’importe quel sélecteur de la feuille de style. Le fond est vert.
Duels de règles en pratique
#.note vs p
p est écrite plus bas..note { background: seagreen; }
p { background: crimson; }#intro vs .note.demo
#intro { background: royalblue; }
.note.demo { background: crimson; }.demo vs .note
.demo { background: royalblue; }
.note { background: seagreen; }:where(#intro) vs p
:where() ramène le poids à zéro, donc la règle avec l’identifiant, bien qu’écrite plus bas, perd face au simple p. Le fond est vert.p { background: seagreen; }
:where(#intro) { background: crimson; }:is(p, #missing) vs .note
:is() prend le poids du sélecteur le plus fort de la liste, même quand l’élément correspond via le p plus faible. Le fond est bleu.:is(p, #missing) { background: royalblue; }
.note { background: crimson; }!important
!important gagne face à une déclaration ordinaire, quel que soit le poids du sélecteur. Le fond est vert malgré l’identifiant.p { background: seagreen !important; }
#intro { background: royalblue; }style=""
style est plus fort que n’importe quel sélecteur de la feuille de style. Le fond est vert.#intro { background: royalblue; }Plus d’exemples
#/* (0, 0, 1) : :where() ramène le poids de #menu à zéro */
:where(#menu) a {
color: #a1a1aa;
}
/* (0, 1, 0) : maintenant elle gagne */
.active {
color: #fbbf24;
}<nav id="menu" class="stage" style="display: flex; gap: 16px;">
<a href="#" style="text-decoration: none;">Cours</a>
<a href="#" class="active" style="text-decoration: none;">Documentation</a>
<a href="#" style="text-decoration: none;">Collections</a>
</nav>Une fois #menu enveloppé dans :where(), une simple classe suffit à mettre en valeur le lien actif.
Compatibilité des navigateurs
#Largement disponible
Fonctionne dans tous les navigateurs modernes, y compris sur mobile. Vous pouvez l’utiliser sans crainte.
- Chrome
- Edge
- Firefox
- Safari
Bonnes pratiques
#- Gardez la spécificité basse et régulière : stylisez surtout avec des classes uniques. Le résultat dépend alors de l’ordre des règles, facile à contrôler.
- Avant de recourir à
!important, vérifiez dans les outils de développement quelle règle gagne et pourquoi.!importantrésout le problème aujourd’hui, mais imposera demain un autre!important. - Enveloppez les styles de base et de bibliothèque dans
:where(). Ils ont alors un poids nul, et n’importe qui peut les écraser avec une seule classe.
Entrées associées
#- #idSélectionne l’élément portant l’identifiant indiqué dans l’attribut id. Il a une spécificité très élevée, donc ses règles sont difficiles à écraser par la suite.
- .classeSélectionne les éléments qui ont la classe indiquée dans l’attribut class. Le sélecteur le plus utilisé pour styliser des composants.
- :where()Fonctionne comme :is(), mais a toujours une spécificité nulle. Idéale pour les styles de base, faciles à redéfinir.
- :is()Fait correspondre l’élément à n’importe quel sélecteur de la liste. Raccourcit les longs sélecteurs répétitifs en une seule écriture.
- :not()Sélectionne les éléments qui ne correspondent à aucun des sélecteurs fournis, ni à aucun de la liste.
- A, BLa virgule combine plusieurs sélecteurs en une seule règle, pour leur donner les mêmes styles sans répéter les déclarations.
Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.