ToolPal
CSS code on a computer screen

Comprendre la spécificité CSS : pourquoi vos styles ne s'appliquent pas

📷 Negative Space / Pexels

Comprendre la spécificité CSS : pourquoi vos styles ne s'appliquent pas

La spécificité CSS est l'une des sources de confusion les plus fréquentes en développement front-end. Découvrez le système (A,B,C), les erreurs classiques, et comment un calculateur de spécificité peut vous faire gagner du temps.

13 avril 20265 min de lecture

Tout développeur front-end connaît ce moment particulier : on écrit une règle CSS, on recharge le navigateur, et rien ne se passe. On ouvre DevTools, on voit sa règle barrée d'un trait, supplantée par un sélecteur qui vient d'on ne sait où.

Réflexe immédiat : ajouter !important.

Le problème, c'est que cette solution de facilité ressemble à un sparadrap sur une fuite. Quelques mois plus tard, la feuille de styles ressemble à un champ de bataille où chaque règle tente de crier plus fort que les autres. Comprendre la spécificité CSS, c'est sortir de ce cycle.

Le système (A, B, C)

La spécificité CSS n'est pas un nombre unique mais un triplet (A, B, C). La comparaison s'effectue de gauche à droite, comme pour des numéros de version. Un sélecteur à (1, 0, 0) bat toujours un sélecteur à (0, 99, 99), quels que soient les cumuls à droite.

A — Sélecteurs d'ID #header, #contenu : chaque sélecteur d'ID ajoute 1 à A, soit (1, 0, 0) par occurrence. C'est pourquoi les bonnes pratiques modernes déconseillent le styling par ID — une fois utilisé, il est très difficile à surcharger sans !important ou un autre ID.

B — Classes, attributs, pseudo-classes Sélecteurs de classe (.nav), d'attribut ([type="submit"]) et pseudo-classes (:hover, :focus, :nth-child()) alimentent B. :not() y contribue également via la spécificité de son argument.

C — Sélecteurs de type et pseudo-éléments div, p, span et les pseudo-éléments ::before, ::after, ::placeholder sont comptés en C.

Ce qui ne compte pas Le sélecteur universel *, les combinateurs (>, +, ~), et surtout :where(), contribuent zéro à la spécificité. Ce dernier point est délibéré et très utile pour les bibliothèques de styles.

Exemples pratiques

/* (0, 0, 1) */
p { color: red; }

/* (0, 1, 0) */
.intro { color: blue; }

/* (0, 1, 1) */
.intro p { color: green; }

/* (1, 0, 0) */
#main { color: orange; }

/* (1, 1, 1) */
#main .contenu p { color: purple; }

Si toutes ces règles ciblent le même élément, (1, 1, 1) l'emporte.

Les idées reçues courantes

Plus un sélecteur est long, plus il est spécifique

Faux. .nav .liste .item a.lien:hover est long mais ne vaut que (0, 4, 2). Un simple #nav avec (1, 0, 0) le bat systématiquement.

La règle écrite en dernier gagne toujours

Uniquement quand les spécificités sont égales. Si les valeurs diffèrent, l'ordre dans le fichier n'a aucune importance — la spécificité prime.

Le comportement de :is(), :not() et :where()

:not() hérite de la spécificité de son argument. :not(.masque) équivaut à (0, 1, 0) à cause de .masque.

:is() prend la spécificité du plus spécifique de ses arguments. :is(#header, .nav, p) vaut (1, 0, 0) à cause de #header — même si l'élément ciblé n'est qu'un .nav. Ce comportement surprend souvent.

:where() vaut toujours zéro, quel que soit son contenu. C'est une mécanique très utile pour les systèmes de design : on peut écrire des règles détaillées dans :where() et laisser n'importe quelle classe simple les surcharger.

Scénario réel : surcharger une bibliothèque de composants

Situation classique en projet :

/* CSS de la bibliothèque */
.ui-btn.ui-btn--primary {
  background-color: #0066cc;
}

/* Ma surcharge */
.mon-bouton {
  background-color: #ff5500;
}

Bibliothèque : (0, 2, 0). Ma règle : (0, 1, 0). Ma règle perd.

Solutions propres :

  1. Doubler la classe : .mon-bouton.mon-bouton monte à (0, 2, 0) — technique valide
  2. Ajouter un contexte parent : .mon-app .mon-bouton atteint également (0, 2, 0)
  3. !important : en dernier recours, si aucune autre option n'est envisageable

Si vous contrôlez la bibliothèque, envelopper les styles de base dans :where() est la solution idéale : les surcharges deviennent triviales.

Le calculateur de spécificité CSS

Plutôt que de compter mentalement, le calculateur de spécificité CSS décompose instantanément n'importe quel sélecteur en valeur (A, B, C).

Cas d'utilisation typiques :

  • Comparer deux règles en conflit pour comprendre immédiatement laquelle doit gagner
  • Vérifier un sélecteur avant de le valider, pour s'assurer que la spécificité reste raisonnable
  • Apprendre : modifier un sélecteur et observer en direct l'évolution des valeurs est l'approche la plus pédagogique

Limites de l'outil

Pour les sélecteurs courants, le calcul est fiable. Les expressions :is() très imbriquées et les sélecteurs Shadow DOM (::slotted(), ::part()) peuvent présenter des cas limites où le résultat n'est pas parfaitement précis. Pour ces situations, les DevTools du navigateur restent la référence.

Écrire du CSS avec une spécificité maîtrisée

Ne pas utiliser les ID pour le style Réservez les ID aux ancres de page et aux références JavaScript. Les utiliser comme sélecteurs CSS introduit une barrière de spécificité difficile à franchir.

Garder les sélecteurs courts .lien-nav est préférable à nav ul li a.lien-nav. Un sélecteur court a une spécificité basse et est moins fragile face aux changements de structure HTML.

Adopter BEM ou une convention similaire Avec BEM (.bloc__element--modificateur), presque tous les sélecteurs restent à (0, 1, 0) et la spécificité devient prévisible et homogène.

Réserver !important aux classes utilitaires .cache, .visuellement-cache, .u-texte-centre — des classes qui doivent toujours l'emporter justifient !important. Pour tout le reste, c'est un signal d'alerte.

Outils complémentaires


La spécificité CSS est un investissement rentable. Une fois les règles intégrées — pourquoi (1, 0, 0) bat (0, 100, 0), comment :where() change la donne, ce que :is() fait à la spécificité — on cesse de se battre contre le navigateur. Les !important s'effacent, les sélecteurs raccourcissent, les surcharges fonctionnent du premier coup. Utilisez le calculateur de spécificité CSS pour gagner du temps sur le débogage, et laissez-vous guider par la logique derrière les chiffres.

Questions Fréquentes

Partager

XLinkedIn

Articles associés