Spécificité

The CSS Podcast - 003: Specificity

Supposons que vous utilisiez le code HTML et CSS suivant:

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

button {
  color: red;
}

Ici, deux règles ciblent le même élément. Chaque règle contient une déclaration qui souhaite définir la couleur du bouton : l'une tente de le colorer en rouge et l'autre en bleu. Quelle déclaration est appliquée à l'élément ?

Comprendre l'algorithme de spécificité CSS est essentiel pour comprendre comment le CSS choisit entre les déclarations concurrentes.

La spécificité est l'une des étapes distinctes de la cascade, qui a été abordée dans le dernier module sur la cascade.

Évaluation de la spécificité

Chaque règle de sélecteur dans une origine 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. Les déclarations des règles les plus spécifiques l'emportent.

Dans un projet réel, l'équilibre consiste à s'assurer que les règles CSS que vous prévoyez d'appliquer s'appliquent, tout en gardant généralement les scores bas pour éviter la complexité. La spécificité ne doit être aussi élevée que nécessaire, plutôt que de viser la plus grande spécificité possible. À l'avenir, il se peut que vous deviez appliquer des styles CSS plus importants. Si vous optez pour la plus grande spécificité, vous compliquerez cette tâche.

La spécificité n'est pas un nombre décimal, mais une triade composée de trois composants: A, B et C.

  • A: spécificité semblable à un ID
  • B: spécificité semblable à une classe
  • C: spécificité semblable à un élément

Il est souvent représenté à l'aide de la notation (A,B,C). Exemple : (1,0,2). La notation A-B-C est également couramment utilisée.

Schéma illustrant les trois composants de la spécificité (A,B,C). Pour chaque composant, le diagramme indique ce qu&#39;il représente et quelques exemples de sélecteurs qui l&#39;affectent.
Schéma illustrant le composant de spécificité auquel différents sélecteurs affectent.

Comparer les spécificités

Les spécificités sont comparées en comparant les trois composants dans l'ordre suivant : la spécificité avec une valeur A plus élevée est plus spécifique ; si les deux valeurs A sont identiques, la spécificité avec une valeur B plus élevée est plus spécifique ; si les deux valeurs B sont également identiques, la spécificité avec une valeur C plus élevée est plus spécifique ; si toutes les valeurs sont identiques, les deux spécificités sont égales.

Par exemple, (1,0,0) est considéré comme plus spécifique que (0,4,3), car la valeur A dans (1,0,0) (qui est 1) est supérieure à la valeur A de (0,4,3) (qui est 0).

Les sélecteurs ont une influence sur la spécificité.

Chaque partie de la triade de spécificité commence par une valeur de 0. La spécificité par défaut est donc (0,0,0). Chaque partie d'un sélecteur augmente la spécificité qui, en fonction du type de sélecteur, augmente la valeur de A, B ou C.

Sélecteur universel

Un sélecteur universel (*) n'ajoute aucune spécificité, laissant sa valeur à la spécificité initiale de (0,0,0).

* {
  color: red;
}

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

Un sélecteur d'élément (type) ou de pseudo-élément ajoute une spécificité semblable à celle d'un élément, ce qui augmente le composant C de 1.

Les exemples suivants ont une spécificité globale de (0,0,1).

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 ajoute une spécificité semblable à une classe, qui augmente le composant B de 1.

Les exemples suivants ont une spécificité de (0,1,0).

Sélecteur de classe

.my-class {
  color: red;
}

Sélecteur de classe pseudo

:hover {
  color: red;
}

Sélecteur d'attribut

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

Sélecteur d'ID

Un sélecteur d'ID ajoute une spécificité semblable à un ID, ce qui augmente le composant C de 1, à condition que vous utilisiez un sélecteur d'ID (#myID) et non un sélecteur d'attribut ([id="myID"]).

Dans l'exemple suivant, la spécificité est (1,0,0).

#myID {
  color: red;
}

Autres sélecteurs

Le CSS comporte de nombreux sélecteurs. Ils ne sont pas tous spécifiques. Par exemple, la pseudo-classe :not() n'ajoute rien au calcul de la 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 a une spécificité de (0,1,1), car il comporte un sélecteur de type (div) et une classe à l'intérieur de :not().

Vérifier vos connaissances

Tester vos connaissances sur le score de spécificité

Quelle est la spécificité de a[href="#"] ?

(0,0,1)
a vaut (0,0,1), mais [href="#"] vaut (0,1,0).
(0,1,0)
Essayez encore. a vaut (0,0,1), mais [href="#"] vaut (0,1,0).
(0,1,1)
a vaut (0,0,1) et [href="#"] vaut (0,1,1), ce qui donne une spécificité totale de (0,1,1).

Facteurs n'ayant aucune incidence sur la spécificité

Voici quelques idées reçues courantes sur les facteurs suivants qui affectent la spécificité.

Attributs de style intégrés

Le CSS appliqué directement à l'attribut style d'un élément n'a aucune incidence sur la spécificité, car il s'agit d'une étape différente de la cascade qui est évaluée avant la spécificité.

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

Pour remplacer cette déclaration à partir d'une feuille de style, vous devez obtenir la victoire de la déclaration à une étape antérieure de la cascade.

Par exemple, vous pouvez y ajouter !important pour qu'il fasse partie de l'origine !important créée par l'auteur.

!important déclarations

Un !important à la fin d'une déclaration CSS n'affecte pas la spécificité, mais place la déclaration dans une origine différente, à savoir !important créé.

Dans l'exemple suivant, la spécificité de .my-class n'est pas pertinente pour que la déclaration !important l'emporte.

.my-class {
  color: red !important;
  color: white;
}

Lorsque deux déclarations sont !important, la spécificité entre à nouveau en jeu, car l'étape d'origine de la cascade n'a pas encore pu déterminer le gagnant.

.branding {
  color: blue !important;
}

button {
  color: red !important;
}

Spécificité dans le contexte

Lorsqu'un sélecteur complexe ou composé est utilisé, chaque partie de ce sélecteur s'ajoute à la spécificité. Prenons l'exemple HTML suivant:

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

Ce lien comporte deux classes. La règle du CSS suivant a une spécificité de (0,0,1):

a {
  color: red;
}

Si vous faites référence à l'une des classes du sélecteur, elle a désormais une spécificité de (0,1,1):

a.my-class {
  color: green;
}

Ajoutez l'autre classe au sélecteur. Il a désormais une spécificité de (0,2,1):

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

Ajoutez l'attribut href au sélecteur. Il dispose désormais d'une spécificité de (0,3,1):

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

Enfin, ajoutez une pseudo-classe :hover à tout cela. Le sélecteur se termine par une spécificité de (0,4,1):

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

Vérifier vos connaissances

Tester vos connaissances sur le score de spécificité

Parmi les sélecteurs suivants, lequel a une spécificité de (0,2,1) ?

article > section
Les éléments ajoutent une spécificité semblable à celle des éléments (composant C). Le sélecteur contient deux éléments, ce qui lui donne une spécificité de (0,0,2).
article.card.dark
Les éléments ajoutent une spécificité semblable à celle des éléments (composant C), tandis que les classes ajoutent une spécificité semblable à celle des classes (composant B). Avec deux classes et un élément, la spécificité de ce sélecteur est (0,2,1).
article:hover a[href]
Les éléments ajoutent une spécificité semblable à celle des éléments (composant C), tandis que les pseudo-classes et les attributs ajoutent une spécificité semblable à celle des classes (composant B). Il existe deux sélecteurs d'éléments (2 × (0,0,1)), un sélecteur d'attribut ((0,0,1)) et un sélecteur de classe ((0,0,1)). La spécificité totale de ce sélecteur est donc de (0,2,2).

Augmenter de manière pragmatique la spécificité

Supposons que vous disposiez d'un code CSS qui se présente comme suit:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Avec du code HTML, cela se présente comme suit:

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

Le bouton a un arrière-plan gris, car le deuxième sélecteur a une spécificité de (0,1,1). En effet, il comporte un sélecteur de type (button), qui est (0,0,1), et un sélecteur d'attribut ([onclick]), qui est (0,1,0).

La règle précédente (.my-button) est égale à (0,1,0), car elle comporte un sélecteur de classe, ce qui est moins spécifique que (0,1,1).

Si vous souhaitez renforcer cette règle, vous pouvez répéter le sélecteur de classe comme suit:

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

button[onclick] {
  background: grey;
}

Le bouton aura désormais un arrière-plan bleu, car le nouveau sélecteur reçoit une spécificité (0,2,0).

En cas d'égalité de spécificité, l'étape suivante de la cascade est appliquée.

Pour l'instant, restons sur l'exemple de bouton et remplaçons le code CSS par le suivant:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

Le bouton a un arrière-plan gris, car les deux sélecteurs ont une spécificité identique de (0,1,0).

Si vous inversez l'ordre des règles dans l'ordre source, le bouton devient bleu.

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

En effet, les deux sélecteurs ont la même spécificité. Dans ce cas, la cascade revient à l'étape d'ordre d'apparition.

Ressources