La priorité des sélecteurs CSS !

La priorité des sélécteurs

Vous connaissez tous les sélecteurs, c’est ce qui permet de spécifier tel élément HTML à un autre et de lui faire appliquer des propriétés comme une position dans une page web ou sa couleur par exemple.

Mais que se passe-t-il si deux règles ciblent le même élément et lui appliquent des valeurs différentes sur une même propriété ? Du style une règle qui met une balise div en rouge et une autre règle qui le met en bleu. Le CSS donne la priorité à une règle en fonction de son poids ! Un poids ? Et bien, voyons ce qui fait qu’une règle est choisie au lieu d’une autre et ça n’a rien à voir avec les kilos qu’elle fait ! C’est parti !

Le score

C’est un des principes liés aux notions de cascade et d’héritage en CSS. On parle de spécificité pour la priorité des sélecteurs, chaque règle à un poids qui influe sur la propriété qui sera appliquée lorsque deux règles rentrent en conflit. Dans l’article, je ne parlerai pas de poids, mais plutôt de score et de points qui permet de mieux cerner ce principe.

C’est le score de notre sélecteur qui déterminera donc qui aura la priorité sur toutes les autres règles. Son score est calculé en fonction du nombre d’éléments, de classe et d’identifiant que compose le sélecteur. En effet, suivant ce qui est utilisé dans le sélecteur pour cibler un élément précis, un nombre de points lui sera attribué ce qui donne notre fameux score. Celui qui a le plus haut score aura donc le dessus et pourra appliquer sans problème toutes ses propriétés sur l’élément qu’elle cible. Si l’élément en question a déjà une propriété définie par une règle avec un score moins élevé, celui-ci sera remplacé par la règle qui a la priorité, à condition toutefois que celle-ci la redéfinisse clairement.

Ce système de score est donc composé d’un nombre de points, mais pas seulement, il y a aussi des catégories de point. Si le score d’une règle à 100 points ou même 1000 points, si une autre règle à un 1 point d’une catégorie supérieur, c’est cette règle qui aura le dessus ! On pourrait voir le score comme ça : 1-0 > 0-100 ou 0-1000.

Mais au fait, que se passe-t-il si une règle qui a la priorité n’a pas de propriété de bordure par exemple et qu’une autre règle avec un score moins élevé lui en met une ? Et bien, il aura quand même une bordure ! Le CSS va chercher sur toutes les règles les propriétés à appliquer sur un élément en commençant par le score le plus élevé et en finissant jusqu’au dernier. Dans son parcours, dès qu’il rencontre une propriété, il appliquera la propriété. Voyons vite l’exemple en bas :

/* Score de 0-0-2 */
HTML div{
    border: 1px solid red; /* remplace la bordure noire de div, div#SpecialDiv n'a pas de propriété de bordure, alors c'est cette valeur qui sera appliquée */
    background-color: bleu; /* Remplacée */
}

/* Score de 0-0-1 */
div{
    position: absolute; /* Remplacée */
    padding: 4px; /* La seule propriété des 3 règles, elle sera appliquée */
    border: 1px solid black; /* Remplacé */
}

/* Score de 1-0-0 */
div#SpecialDiv{
    background-color: red; /* Remplace la couleur bleue de HTML div*/
    position: static; /* Annule la position absolute de div */
    margin: 4px; /* La seule propriété des 3 règles, elle sera appliquée  */
}

Dans cet exemple, un même élément possédant l’identifiant SpecialDiv, dispose de 3 règles CSS. Les règles seront appliquées en donnant la priorité à div#SpecialDiv, suivi de HTML div et enfin de div (1-0-0 > 0-0-2 > 0-0-1). L’élément aura donc une couleur rouge, une position statique, une bordure d’un pixel en rouge, un padding et une marge de 4px.

L’attribution des points

On passe maintenant au système de points, mais comment est calculé le score ainsi que les catégories ? Comme je l’ai dit plus haut, son score est calculé en fonction du nombre de sélecteurs, mais aussi du type de sélecteur utilisé. Dans le listing plus bas, nous partons du score le plus bas jusqu’au plus haut !

  • Tout ce qui désigne un élément, les sélecteurs de types, comme par exemple div, span ou table, un point lui sera attribué. Score : 1
  • Le nombre d’éléments dans un sélecteur contribue au score total de la règle. Si le sélecteur contient 3 éléments comme HTML body div, cela lui donne 3 points ! Score : 3
  • Les pseudo-éléments comme ::after, ::before ou ::first-line par exemple, rentre dans la même catégorie que les éléments. html body div::after, aura 4 points ! Score : 4
  • Pour tout ce qui désigne une classe, donc les sélecteurs de classe, un point de la deuxième catégorie lui sera attribué, faisant passer la règle CSS à un niveau qui, peu importe le nombre d’éléments que peut contenir une autre règle, aura la priorité sur celui-ci. Score : 1-0 et même si une règle possède 1000 éléments, la catégorie supérieure aura toujours la priorité, car comme vu plus haut 1-0 > 0-1000 !
  • Le nombre de classes désignées dans le sélecteur contribue également au score de la règle. Si le sélecteur en question à .classe1 .classe2 .classe3, cela lui donne 3 points de la deuxième catégorie ! Score : 3-0
  • Si des éléments sont ajoutés en plus des classes, comme html.classe1 body.classe2 div.classe3 (mettre des classes sur HTML et body n’est pas très pertinent :/, mais c’est juste pour l’exemple), cela lui donnera 6 points, dont 3 de la deuxième catégorie. Score : 3-3
  • Dans la deuxième catégorie, nous avons les classes qui ajoutent des points là-dedans, mais il y a aussi les sélecteurs d’attribut et les pseudo-classes qui rentrent dans cette catégorie. Un HTML container input.classe1[type=checkbox]:hover aura le même score que celui vu juste en haut !
  • Tout ce qui désigne un identifiant dans un sélecteur, donc les sélecteurs d’identifiant, un point de la 3e catégorie lui sera attribué. Score : 1-0-0. Bien entendu le nombre d’identifiant, de classe et d’élément influence le score.
  • Si notre règle est une règle inline, que ça soit par l’ajout de l’attribut style="" dans le code HTML ou d’un style par JavaScript, un score de 1-0-0-0 lui sera attribué. C’est un autre type de catégorie qui ne rentre pas vraiment dans le système de points, disons plutôt qu’il ne peut y avoir qu’un point dans cette catégorie et une règle inline n’aura que le score de 1-0-0-0. C’est logique qu’en on y pense, en mettant une règle inline, on applique une règle qu’à un seul élément. Une règle inline aura donc toujours la priorité face à une règle tirée d’un fichier CSS.
  • Si une propriété a le mot-clé !important, un score de 1-0-0-0-0 lui sera attribué, ayant la priorité sur tout. Similaire aux règles inline, un seul point ne peut être attribué dans cette catégorie.

Une petite illustration en anglais qui résume le listing :

Les Exceptions

… car il y en a toujours.

Que se passe-t-il si deux règles ont exactement le même score ? Et bien dans ce cas, celui qui aura la priorité sera la dernière règle déclarée. Une règle placée au début d’un fichier CSS sera remplacée par la règle écrite en fin de fichier, si les deux ont le même score.

Qu’est ce que ça fait si j’ajoute des sélecteurs de combinaisons ? Le nombre et le type de combinateur n’influent pas sur le score de la règle, ça vaut 0 point ! Dans le listing plus haut, j’ai utilisé le combinateur d’enfant avec l’espace, mais j’aurais très bien pu utiliser d’autre combinateur, comme le +, >, etc.

Le sélecteur universel qui est un sélecteur de base vaut lui aussi 0 ! Écrire une règle avec un *.div ne vaudra que un point et pas deux, il n’y a pas non plus de point dans des catégories supérieures.

La pseudo-classe de négation vaut également 0, mais les sélecteurs qui sont placés dans les parenthèses compte dans le score ! On pourrait croire qu’un div:not(#id) vaut 1-1-1, car les pseudo-classes donnent un point de la 2e catégorie, mais en réalité cela vaut : 1-0-1 !

Alors maintenant que vous savez comment ça marche, les règles ne vous surprendront plus dans leur façon d’appliquer une propriété !

Et en cadeau, je vous donne un lien sur cet outil en ligne qui calcule automatiquement le score d’une règle CSS, ou pour utiliser le terme exact, le poids d’un sélecteur. Entrez juste votre sélecteur dans la zone prévue à cet effet et son poids sera calculé automatiquement ! 😎

A++ 🙂

Partager l’article :
  •  
  •  
  •  
  •  
  •  
  •  
    1
    Partage
  • 1
  •  
  •  

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.