Spécificité

Podcast CSS – 003: Spécificité

Supposons que vous utilisiez les codes HTML et CSS suivants:

<button class="branding">Hello, Specificity!</button>
button {
  color: red;
}

.branding {
  color: blue;
}

Il y a deux règles concurrentes. L'une colorera le bouton en rouge et l'autre en bleu. Quelle règle s'applique à l'élément ? Il est essentiel de comprendre l'algorithme de la spécification CSS concernant la spécificité pour comprendre comment le CSS décide entre des règles concurrentes.

La spécificité est l'une des quatre étapes distinctes de la cascade, que nous avons abordée dans le dernier module concernant la cascade.

Évaluation de la spécificité

Chaque règle de sélecteur reçoit un score. Vous pouvez considérer la spécificité comme un score total, et chaque type de sélecteur gagne des points pour ce score. Le sélecteur ayant le score le plus élevé l'emporte.

Avec la spécificité d'un projet réel, l'équilibre consiste à s'assurer que les règles CSS que vous prévoyez d'appliquer sont effectivement appliquées, tout en limitant généralement les scores pour éviter la complexité. Le score doit être aussi élevé que nécessaire, au lieu de viser le score le plus élevé possible. À l'avenir, vous devrez peut-être appliquer des CSS véritablement plus importants. Si vous visez le score le plus élevé, vous rendra votre travail difficile.

Noter chaque type de sélecteur

Chaque type de sélecteur permet de gagner des points. Vous additionnez tous ces points pour calculer la spécificité globale d'un sélecteur.

Sélecteur universel

Un sélecteur universel (*) n'a aucune spécificité et n'obtient 0 point. Cela signifie que toute règle avec un ou plusieurs points la remplacera

* {
  color: red;
}

Sélecteur d'éléments ou de pseudo-éléments

Un sélecteur d'élément (type) ou de pseudo-élément obtient 1 point de spécificité .

Sélecteur de type

div {
  color: red;
}

Sélecteur de pseudo-éléments

::selection {
  color: red;
}

Sélecteur de classe, de pseudo-classe ou d'attribut

Un sélecteur de classe, de pseudo-classe ou d'attribut obtient 10 points de spécificité.

Sélecteur de classe

.my-class {
  color: red;
}

Sélecteur de pseudo-classe

:hover {
  color: red;
}

Sélecteur d'attribut

[href='#'] {
  color: red;
}

La pseudo-classe :not() n'ajoute rien au calcul de spécificité. Toutefois, les sélecteurs transmis en tant qu'arguments sont ajoutés au calcul de la spécificité.

div:not(.my-class) {
  color: red;
}

Cet exemple présente 11 points de spécificité, car il comporte un sélecteur de type (div) et une classe à l'intérieur de :not().

Sélecteur d'ID

Un sélecteur d'ID obtient 100 points de spécificité, à condition que vous utilisiez un sélecteur d'ID (#myID) et non un sélecteur d'attributs ([id="myID"]).

#myID {
  color: red;
}

Attribut de style intégré

Le code CSS appliqué directement à l'attribut style de l'élément HTML obtient un score de spécificité de 1 000 points. Autrement dit, pour le remplacer en CSS, vous devez écrire un sélecteur extrêmement spécifique.

<div style="color: red"></div>

Ajout de la règle !important.

Enfin, un !important à la fin d'une valeur CSS obtient un score de spécificité de 10 000 points. Il s'agit du niveau de spécificité le plus élevé qu'un élément individuel peut obtenir.

Une règle !important est appliquée à une propriété CSS. Par conséquent, tout ce qui se trouve dans la règle globale (sélecteur et propriétés) n'obtient pas le même score de spécificité.

.my-class {
  color: red !important; /* 10,000 points */
  background: white; /* 10 points */
}

Testez vos connaissances

Tester vos connaissances sur l'évaluation de la spécificité

Quel est le score de spécificité de a[href="#"] ?

1
a vaut 1 point, mais [href="#"] vaut 10 points.
5
Essayez encore.
11
a vaut 1 point et [href="#"] 10 points, soit un score total de 11 points.

Spécificité en contexte

La spécificité de chaque sélecteur correspondant à un élément est additionnée. Prenons l'exemple de code HTML suivant:

<a class="my-class another-class" href="#">A link</a>

Ce lien comporte deux classes. Ajoutez le CSS suivant pour qu'il obtienne un point de spécificité:

a {
  color: red;
}

Référence l'une des classes de cette règle, qui comporte désormais 11 points de spécificité:

a.my-class {
  color: green;
}

Ajoutez l'autre classe au sélecteur. Elle dispose maintenant de 21 points de spécificité:

a.my-class.another-class {
  color: rebeccapurple;
}

Ajoutez l'attribut href au sélecteur. Il dispose désormais de 31 points de spécificité:

a.my-class.another-class[href] {
  color: goldenrod;
}

Enfin, ajoutez une pseudo-classe :hover à tout cela. Le sélecteur se termine par 41 points de spécificité:

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

Testez vos connaissances

Tester vos connaissances sur l'évaluation de la spécificité

Parmi les sélecteurs suivants, lequel vaut 21 points ?

article > section
Les éléments valent 1 point. Il y a 2 éléments dans le sélecteur, ce qui donne 2 points.
article.card.dark
Les éléments valent 1 point, les classes valent 10 points, et avec deux classes et un élément, ce sélecteur vaut 21 points.
article:hover a[href]
Les éléments valent 1 point, les pseudo-classes et les attributs valent 10 points, 2 points pour les éléments et 20 points pour les attributs et les classes. Ce sélecteur vaut donc 22 points.

Visualisation de la spécificité

Dans les diagrammes et les calculateurs de spécificité, la spécificité est souvent représentée comme suit:

Schéma illustrant les sélecteurs les plus spécifiques aux moins spécifiques

Le groupe de gauche se compose de id sélecteurs. Le second groupe comprend les sélecteurs de classe, d'attribut et de pseudo-classe. Le dernier groupe est constitué des sélecteurs d'éléments et de pseudo-éléments.

Pour référence, le sélecteur suivant est 0-4-1:

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

Testez vos connaissances

Tester vos connaissances sur la visualisation de la spécificité

Quel sélecteur est 1-2-1 ?

section#specialty.dark
Ce sélecteur est représenté sous la forme 1-1-1.
#specialty:hover li.dark
🎉
[data-state-rad].dark#specialty:hover
Ce sélecteur est représenté sous la forme 1-3-0.
li#specialty section.dark
Ce sélecteur est représenté sous la forme 1-1-2.

Augmenter pragmatiquement la spécificité

Imaginons que notre code CSS se présente comme suit:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Avec du code HTML qui ressemble à ceci:

<button class="my-button" onclick="alert('hello')">Click me</button>

L'arrière-plan du bouton est gris, car le deuxième sélecteur gagne 11 points de spécificité (0-1-1). En effet, il possède un sélecteur de type (button), à savoir 1 point, et un sélecteur d'attribut ([onclick]), qui équivaut à 10 points.

La règle précédente (.my-button) obtient 10 points (0-1-0), car elle comporte un sélecteur de classe.

Si vous souhaitez booster cette règle, répétez le sélecteur de classe comme suit:

.my-button.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Le bouton présente désormais un arrière-plan bleu, car le nouveau sélecteur obtient un score de spécificité de 20 points (0-2-0).

Avec un score de spécificité correspondant, l'instance la plus récente gagne.

Poursuivons l'exemple du bouton pour l'instant et changeons le CSS de la manière suivante:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

Le bouton a un fond gris, car les deux sélecteurs ont le même score de spécificité (0-1-0).

Si vous changez les règles dans l'ordre des sources, le bouton devient bleu.

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

Il s'agit de la seule occurrence où un CSS plus récent gagne. Pour ce faire, elle doit correspondre à la spécificité d'un autre sélecteur qui cible le même élément.

Ressources