Comment sont calculés les points de spécificité CSS

125

En recherchant la spécificité, je suis tombé sur ce blog - http://www.htmldog.com/guides/cssadvanced/specificity/

Il déclare que la spécificité est un système de pointage pour CSS. Cela nous dit que les éléments valent 1 point, les classes valent 10 points et les ID valent 100 points. Il va également de soi que ces points sont totalisés et que le montant global est la spécificité de ce sélecteur.

Par exemple:

body = 1 point
body .wrapper = 11 points
body .wrapper #container = 111 points

Donc, en utilisant ces points, je m'attends à ce que le CSS et le HTML suivants aboutissent à un texte bleu:

#a {
    color: red;
}

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o {
  color: blue;
}
<div class="a">
  <div class="b">
    <div class="c">
      <div class="d">
        <div class="e">
          <div class="f">
            <div class="g">
              <div class="h">
                <div class="i">
                  <div class="j">
                    <div class="k">
                      <div class="l">
                        <div class="m">
                          <div class="n">
                            <div class="o" id="a">
                              This should be blue.
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Pourquoi le texte est-il rouge alors que 15 classes équivaudraient à 150 points par rapport à 1 ID qui équivaut à 100 points?

Apparemment, les points ne sont pas simplement totalisés; ils sont concaténés. En savoir plus à ce sujet ici - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

Cela signifie-t-il que les classes de notre sélecteur = 0,0,15,0OR 0,1,5,0?

(mon instinct me dit qu'il est l'ancien, comme nous le savons les regards de la spécificité du sélecteur d'ID comme ceci: 0,1,0,0)

Sam
la source
Voici quelque chose de bizarre aussi: stackoverflow.com/questions/25565928/…
Armel Larcier

Réponses:

138

La réponse de Pekka est pratiquement correcte, et probablement la meilleure façon de penser au problème.

Cependant, comme beaucoup l'ont déjà souligné, la recommandation CSS du W3C stipule que «la concaténation des trois nombres abc (dans un système de nombres avec une grande base) donne la spécificité». Donc, le geek en moi devait juste déterminer la taille de cette base.

Il s'avère que la "très grande base" employée (au moins par les 4 navigateurs les plus couramment utilisés * ) pour implémenter cet algorithme standard est 256 ou 2 8 .

Ce que cela signifie est qu'un style spécifié avec 0 ids et 256 noms de classe sera sur-monter un style spécifié avec seulement 1 id. J'ai testé cela avec quelques violons:

Il y a donc effectivement un «système de points», mais ce n'est pas la base 10. C'est la base 256. Voici comment cela fonctionne:

(2 8 ) 2 ou 65536, multiplié par le nombre d'identifiants dans le sélecteur
+ (2 8 ) 1 ou 256, multiplié par le nombre de noms de classe dans le sélecteur
+ (2 8 ) 0 ou 1, multiplié par le nombre de balises- noms dans le sélecteur

Ce n'est pas très pratique pour les exercices du fond de l'enveloppe pour communiquer le concept.
C'est probablement pourquoi les articles sur le sujet utilisent la base 10.

***** [Opera utilise 2 16 (voir le commentaire de karlcow). Certains autres moteurs de sélection utilisent l' infini - effectivement aucun système de points (voir le commentaire de Simon Sapin).]

Mise à jour, juillet 2014:
Comme Blazemonger l'a souligné plus tôt dans l'année, les navigateurs Webkit (chrome, safari) semblent maintenant utiliser une base supérieure à 256. Peut-être 2 16 , comme Opera? IE et Firefox utilisent toujours 256.

Faust
la source
34
Important: notez que le nombre 256 n'est pas dans les spécifications . Ainsi, cette réponse décrit un détail d'implémentation (certes utile).
Matt Fenwick
6
Non seulement 256 n'est pas dans la spécification comme l'a dit @MattFenwick, mais cela varie également selon l'implémentation. Il est apparemment plus grand dans Opera. Dans WeasyPrint et cssselect c'est "infini": j'utilise un tuple d'entiers au lieu d'un seul entier.
Simon Sapin
3
@Faust Opera utilise 16 bits au lieu de 8
karlcow
4
Cette réponse a une description plus pratique que la réponse de Pekka, pour être honnête. En gros, ce que dit @Matt Fenwick: ce que vous décrivez est une implémentation pratique de la spécification. Un problème imparfait, mais pas un pour quoi quoi que ce soit devrait être fait, que ce soit par les auteurs ou les implémenteurs.
BoltClock
7
256 semble être insuffisant dans les versions actuelles de webkit (Chrome et Safari), ce qui souligne davantage le point de @ MattFenwick.
Blazemonger
28

Bonne question.

Je ne peux pas dire avec certitude - tous les articles que je parviens à trouver évitent l'exemple de plusieurs classes, par exemple ici - mais je suppose que lorsqu'il s'agit de comparer la spécificité entre un sélecteur de classe et un ID , la classe est calculée avec un valeur de 15seulement, aussi détaillée soit-elle.

Cela correspond à mon expérience dans la façon dont la spécificité se comporte.

Cependant, il doit y avoir un certain empilement de classes car

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o

est plus spécifique que

.o

la seule explication que j'ai est que la spécificité des classes empilées est calculée uniquement les unes par rapport aux autres mais pas par rapport aux ID.

Mise à jour : je l'ai à mi-chemin maintenant. Ce n'est pas un système de points et les informations sur les classes pesant 15 points sont incorrectes. C'est un système de numérotation en 4 parties très bien expliqué ici .

Le point de départ est 4 chiffres:

style  id   class element
0,     0,   0,    0

Selon l' explication du W3C sur la spécificité , les valeurs de spécificité pour les règles susmentionnées sont:

#a            0,1,0,0    = 100
classes       0,0,15,0   = ... see the comments

il s'agit d'un système de numérotation avec une base très large (non définie?).

Je crois comprendre que parce que la base est très grande, aucun nombre dans la colonne 4 ne peut battre un nombre> 0 dans la colonne 3, la même chose pour la colonne 2, colonne 1 ... Est-ce correct?

Je serais intéressé de savoir si quelqu'un avec une meilleure compréhension des mathématiques que moi pourrait expliquer le système de numérotation et comment le convertir en décimal lorsque les éléments individuels sont plus grands que 9.

Pekka
la source
C'est parce que c'est entre .o et .a .b etc. Donc, il les considérerait collectivement. Mais entre un ID et une classe, par exemple: .a et #a, l'ID sera toujours écrasant. Il ne comptera (je suppose) qu'entre les classes lorsqu'il n'y a pas d'attr plus puissant. Par exemple, la classe passera par l'élément et l'identifiant par-dessus la classe.
Sphvn
@Ozaki c'est ce que je suppose aussi, mais cela contredit ce que l'OP dit sur le système de points. Il doit y avoir plus en jeu. J'aimerais voir les règles derrière cela.
Pekka
Je viens de réaliser que nous sommes tous les deux arrivés à la même conclusion. Excellent travail!
Sam
5
Pour le côté mathématique, nous pouvons travailler ici en base 16 (car aucun des nombres individuels ne dépasse 15). Donc 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240256> 240 donc le sélecteur d'ID gagne.
Matthew Wilson
1
Oui, vous pouvez considérer les calculs de spécificité comme étant effectués dans un système numérique avec une grande base. Je pense que le terme «concaténation» (également utilisé dans la spécification) est une bien meilleure description. (Je suis venu ici après avoir répondu à une nouvelle question qui s'avère être une dupe de celle-ci, allez comprendre ...)
BoltClock
9

L' ébauche de travail actuelle des sélecteurs de niveau 4 décrit bien la spécificité en CSS:

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

Cela signifie que les valeurs A, B et C sont complètement indépendantes l'une de l'autre.

15 classes ne donnent pas à votre sélecteur un score de spécificité de 150, cela lui donne une valeur B de 15. Une seule valeur A suffit pour le maîtriser.

Comme métaphore, imaginez une famille de 1 grand-parent, 1 parent et 1 enfant. Cela pourrait être représenté par 1,1,1 . Si le parent a 15 enfants, cela n'en fait pas soudainement un autre parent ( 1,2,0 ). Cela signifie que le parent a beaucoup plus de responsabilités qu'il n'en avait avec un seul enfant ( 1,1,15 ). ;)

La même documentation poursuit également:

En raison des limitations de stockage, les implémentations peuvent avoir des limitations sur la taille de A , B ou c . Si tel est le cas, les valeurs supérieures à la limite doivent être fixées à cette limite et ne pas déborder.

Cela a été ajouté pour résoudre le problème présenté dans la réponse de Faust , selon laquelle les implémentations CSS de 2012 ont permis aux valeurs de spécificité de déborder les unes dans les autres.

En 2012, la plupart des navigateurs implémentaient une limitation de 255, mais cette limitation était autorisée à déborder. 255 classes avaient un score de spécificité A, B, c de 0,255,0 , mais 256 classes débordaient et avaient un score A, B, c de 1,0,0 . Soudain, notre valeur B est devenue notre valeur A. La documentation des sélecteurs de niveau 4 irradie complètement ce problème en déclarant que la limite ne peut jamais être autorisée à dépasser. Avec cette implémentation, les classes 255 et 256 auraient le même score A, B, c de 0,255,0 .

Le problème donné dans la réponse de Faust a depuis été corrigé dans la plupart des navigateurs modernes.

James Donnelly
la source
8

J'utilise actuellement le livre CSS Mastery: Advanced Web Standards Solutions .

Le chapitre 1, page 16 dit:

Pour calculer la spécificité d'une règle, chaque type de sélecteur se voit attribuer une valeur numérique. La spécificité d'une règle est alors calculée en additionnant la valeur de chacun de ses sélecteurs. Malheureusement, la spécificité n'est pas calculée en base 10 mais en un nombre de base élevé et non spécifié. Cela permet de garantir qu'un sélecteur hautement spécifique, tel qu'un sélecteur d'ID, n'est jamais remplacé par de nombreux sélecteurs moins spécifiques, tels que des sélecteurs de type.

(c'est moi qui souligne) et

La spécificité d'un sélecteur se décompose en quatre niveaux constitutifs: a, b, c et d.

  • si le style est un style en ligne, alors a = 1
  • b = le nombre total de sélecteurs d'identifiant
  • c = le nombre de sélecteurs de classe, de pseudo-classe et d'attribut
  • d = le nombre de sélecteurs de type et de sélecteurs de pseudo-éléments

Il poursuit en disant que vous pouvez souvent faire le calcul en base 10, mais seulement si toutes les colonnes ont des valeurs inférieures à 10.


Dans vos exemples, les identifiants ne valent pas 100 points; chacun vaut des [0, 1, 0, 0]points. Par conséquent, un identifiant bat 15 classes car il [0, 1, 0, 0]est plus grand que [0, 0, 15, 0]dans un système de numérotation à base élevée.

Matt Fenwick
la source
4

J'aime comparer le classement de la spécificité au tableau des médailles des Jeux Olympiques (première méthode d'or - basée d'abord sur le nombre de médailles d'or, puis d'argent et enfin de bronze).

Cela fonctionne également avec votre question (grand nombre de sélecteurs dans un groupe de spécificité). La spécificité a considéré chaque groupe séparément. Dans le monde réel, j'ai très rarement vu des cas avec plus d'une douzaine de sélecteurs).

Il existe également un assez bon calculateur de spécificité disponible ici . Vous pouvez y mettre votre exemple (#a et .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) et voir les résultats.

Exemple de tableau des médailles des Jeux Olympiques de Rio 2016 entrez la description de l'image ici

rkarczmarczyk
la source
3

Je ne pense pas que l'explication du blog soit correcte. La spécification est ici:

http://www.w3.org/TR/CSS2/cascade.html#specificity

Les "points" d'un sélecteur de classe ne peuvent pas être plus importants qu'un sélecteur "id". Ça ne marche pas comme ça.

Matthew Wilson
la source
Comme je l'ai dit dans ma réponse. ^^ Cependant, cela fait une différence si vous en avez plusieurs du même type (élément, classe, id). Mais c'est assez évident si les 5èmes disent rouge et 3 disent bien bleu Je vais bien au rouge.
Sphvn
Le libellé autour de la spécificité n'a probablement pas beaucoup changé entre CSS2 et CSS2.1, mais vous devriez vraiment pointer vers la spécification CSS2.1 dans les discussions futures car elle remplace complètement CSS2 qui était en général cassé au moment de la publication.
Robin Whittleton
1

Je dirais que:

Element < Class < ID

Je pense qu'ils ne s'empilent qu'en fonction de ce que vous obtenez s'il est multiple du même. Ainsi, une classe remplacera toujours l'élément et l'ID par-dessus la classe, mais s'il s'agit de savoir lequel des 4 éléments où 3 est bleu et 1 rouge, il sera bleu.

Par exemple:

.a .b .c .d .e .f .g .h .i .j .k .l
{
color: red;
}

 .m .n .o
{
color blue;
}

Devrait devenir rouge.

Voir l' exemple http://jsfiddle.net/RWFWq/

"si les 5ème disent rouge et 3 disent bien bleu je vais bien rouge"

Sphvn
la source