FreeToGenerate.com

Un identifiant vaut 100 et une classe 10, donc onze classes battent un identifiant ? Non — et onze, c’est précisément là que ce raccourci commence à mentir.

0-11-0

Comment chaque partie a été comptée

  • .btnBUn sélecteur de classe, compté dans la deuxième colonne.
  • .btn-primaryBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-activeBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-largeBUn sélecteur de classe, compté dans la deuxième colonne.
  • .has-iconBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-roundedBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-blockBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-loadingBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-disabledBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-focusBUn sélecteur de classe, compté dans la deuxième colonne.
  • .is-hoverBUn sélecteur de classe, compté dans la deuxième colonne.
A
A — identifiants
B
B — classes, attributs et pseudo-classes
C
C — balises et pseudo-éléments

Lequel l’emporte

0-11-0vs1-0-0

Le second sélecteur l’emporte

Le score en base 10 qu’on enseigne partout

Score: 110 vs 100

Le raccourci se trompe ici. La spécificité, ce sont trois nombres comparés colonne par colonne, et non un total — c’est pourquoi aucune quantité de classes ne l’emporte jamais sur un identifiant, si haut que monte le score.

Aussi disponible en : English · Español · Português · العربية

Calculateur de spécificité CSS

La spécificité d’un sélecteur sous la forme des trois nombres que la cascade compare réellement, chaque partie justifiée, et la réponse du raccourci à côté de la vraie.

Qu’est-ce que la spécificité CSS ?

Lorsque deux règles CSS s’appliquent au même élément et touchent la même propriété, c’est la spécificité qui décide laquelle l’emporte. Elle se calcule à partir du seul sélecteur — ni de l’endroit où se trouve la règle, ni de l’air compliqué qu’elle a — et la spécification des sélecteurs la définit comme trois décomptes, non comme un nombre.

Le premier, A, est le nombre de sélecteurs d’identifiant. Le deuxième, B, compte ensemble les sélecteurs de classe, les sélecteurs d’attribut et les pseudo-classes : un sélecteur d’attribut pèse exactement autant qu’une classe. Le troisième, C, compte les sélecteurs de balise et les pseudo-éléments. Le sélecteur universel ne compte pour rien.

Collez un sélecteur ci-dessus et vous obtenez ces trois nombres, plus une ligne par partie expliquant dans quelle colonne elle est tombée et pourquoi. Ajoutez un second sélecteur et l’outil vous dit lequel des deux l’emporterait.

Comment s’en servir

  1. Saisissez ou collez un sélecteur. De div jusqu’à #nav .item:not(.disabled)::before. Les listes de sélecteurs séparées par des virgules fonctionnent aussi, et chaque entrée est comptée pour elle-même.
  2. Lisez le détail, pas seulement le total. Chaque sélecteur simple a sa propre ligne indiquant dans quelle colonne il a compté et pourquoi : un total surprenant est ainsi expliqué plutôt qu’asséné.
  3. Ajoutez un second sélecteur pour comparer. Vous obtenez le vainqueur, et à côté le score en base 10 — avec un avertissement dans les cas où ce raccourci désigne le mauvais.

Pourquoi onze classes ne battent pas un identifiant

Presque tout le monde apprend la spécificité comme de l’arithmétique : un identifiant vaut 100, une classe 10, une balise 1, on additionne et le plus grand nombre gagne. C’est un mensonge utile qui fonctionne pour presque tous les sélecteurs que l’on écrit, puis cesse de fonctionner sans prévenir.

La spécification est explicite : les trois nombres se comparent une colonne à la fois. Le plus grand A l’emporte d’office, et ce n’est qu’en cas d’égalité sur A que l’on regarde B, puis seulement C. Pas de retenue, pas de total, pas de taux de change. Un identifiant l’emporte sur n’importe quel nombre de classes — cent, mille.

Onze est l’endroit où le raccourci commence à mentir, et ce n’est pas une supposition. Onze classes marquent 110 contre les 100 d’un identifiant : l’arithmétique dit donc que les classes gagnent, là où la cascade dit que c’est l’identifiant. Dix classes marquent encore 100, une égalité que le raccourci tranche comme la vraie règle, par pur hasard. L’outil est livré avec exactement cette paire chargée, pour que vous voyiez les deux modèles diverger plutôt que de le croire sur parole.

Ce n’est pas non plus un cas d’école. Une feuille de styles utilitaire empile les classes sur un même élément comme allant de soi, et la spécification note que répéter un sélecteur simple augmente bel et bien la spécificité : .btn.btn.btn vaut 0-3-0. Onze est plus proche qu’il n’y paraît.

Les parties qui piègent

Quatre pseudo-classes ont leurs propres règles, et c’est là que les calculs à la main dérapent. :is(), :not() et :has() ne se comptent pas elles-mêmes : chacune prend la spécificité du sélecteur le plus spécifique qu’elle contient, si bien que :not(#a) vaut un identifiant entier. :where() fait l’inverse, et c’est la plus utile : elle est remplacée par zéro, donc tout ce qu’elle contient ne contribue en rien, si spécifique que cela paraisse — ce qui en fait l’outil adéquat pour des styles par défaut que l’on veut faciles à surcharger.

:nth-child() et :nth-last-child() forment la paire obscure. Elles comptent pour une pseudo-classe à elles seules, puis ajoutent le sélecteur le plus spécifique d’une clause of s’il y en a une : :nth-child(2n of .item) vaut donc 0-2-0 et non 0-1-0.

Vient ensuite un piège purement historique. :before, :after, :first-line et :first-letter sont des pseudo-éléments écrits avec un seul deux-points, toléré par compatibilité avec CSS2. Ce deux-points unique leur donne l’air de pseudo-classes, et ils comptent malgré tout dans la troisième colonne avec les balises. Tout autre nom à deux-points unique est une véritable pseudo-classe et compte dans la deuxième.

Limites honnêtes

La spécificité n’est qu’une étape de la cascade, et cette page ne calcule que celle-là. Avant elle viennent l’origine et l’importance : une déclaration !important l’emporte sur une déclaration normale quoi que disent les sélecteurs, et les couches de cascade sont elles aussi examinées avant la spécificité. Les styles en ligne se situent hors du triplet du sélecteur, et aucun sélecteur que vous puissiez écrire ne les surpasse. Après la spécificité, si deux règles restent à égalité, c’est la dernière dans l’ordre du code qui l’emporte — c’est ce que signifie ici le résultat d’égalité.

Le calcul suppose également un sélecteur valide. L’outil lit ce que vous tapez sans vérifier qu’un navigateur l’accepterait : une coquille sera donc comptée plutôt que refusée, et les pseudo-classes préfixées par un fabricant ou fraîchement proposées sont traitées comme ordinaires, sauf si elles figurent parmi les cas particuliers ci-dessus.

Autre chose à savoir : la spécification autorise les implémentations à plafonner les trois valeurs si elles manquent de place, si bien qu’un sélecteur absurde peut être écrêté dans un vrai navigateur au lieu d’être compté exactement. Rien de ce que l’on écrit à la main n’en approche.

Les nombres présentés ici ont été vérifiés contre les quatorze exemples résolus de la spécification elle-même et, séparément, contre une implémentation de référence sur 980 sélecteurs générés, sans le moindre désaccord.

Pourquoi est-ce gratuit ?

Parce que cela ne coûte rien à faire tourner. L’analyse et le décompte ont lieu dans votre navigateur ; aucun sélecteur n’est envoyé, aucun serveur ne voit votre feuille de styles, et il n’y a pas de compte.

Les règles viennent de la spécification des sélecteurs CSS et non d’un tutoriel, et les tests qui les vérifient sont conservés à côté du code — y compris les exemples de la spécification elle-même, ce qui est une exigence plus haute que de s’accorder avec un autre calculateur.