Como são calculados os pontos na especificidade do CSS


124

Pesquisando a especificidade, me deparei com este blog - http://www.htmldog.com/guides/cssadvanced/specificity/

Ele afirma que a especificidade é um sistema de pontuação para CSS. Diz-nos que os elementos valem 1 ponto, as classes valem 10 pontos e os IDs valem 100 pontos. Além disso, também diz que esses pontos são totalizados e o valor total é a especificidade do seletor.

Por exemplo:

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

Portanto, usando esses pontos, espero que os seguintes CSS e HTML resultem no texto sendo azul:

#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>

Por que o texto é vermelho quando 15 classes equivalem a 150 pontos em comparação com 1 ID, que é igual a 100 pontos?

Aparentemente, os pontos não são apenas totalizados; eles são concatenados. Leia mais sobre isso aqui - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

Isso significa que as classes em nosso seletor = 0,0,15,0OR 0,1,5,0?

(meus instintos me dizem que é o primeiro, como sabemos aparência especificidade do seletor de ID como este: 0,1,0,0)


Respostas:


137

A resposta de Pekka é praticamente correta e provavelmente a melhor maneira de pensar sobre o assunto.

No entanto, como muitos já apontaram, a recomendação do CSS do W3C afirma que "concatenar os três números abc (em um sistema numérico com uma base grande) fornece a especificidade". Então, o nerd em mim só tinha que descobrir quão grande é essa base.

Acontece que a "base muito grande" empregada (pelo menos pelos 4 navegadores mais usados * ) para implementar esse algoritmo padrão é 256 ou 2 8 .

O que isto significa é que um estilo especificado com 0 ids e 256 de classe-nomes irá sobrepor-se um estilo especificado com apenas 1 id. Eu testei isso com alguns violinos:

Portanto, existe efetivamente um "sistema de pontos", mas não é a base 10. É a base 256. Eis como funciona:

(2 8 ) 2 ou 65536, vezes o número de IDs no seletor
+ (2 8 ) 1 ou 256, vezes o número de nomes de classes no seletor
+ (2 8 ) 0 ou 1, vezes o número de tags- nomes no seletor

Isso não é muito prático para exercícios de retaguarda para comunicar o conceito.
Provavelmente é por isso que os artigos sobre o assunto estão usando a base 10.

***** [Opera usa 2 16 (veja o comentário de karlcow). Alguns outros mecanismos seletores usam infinito - efetivamente, nenhum sistema de pontos (veja o comentário de Simon Sapin).]

Atualização, julho de 2014:
Como o Blazemonger apontou no início do ano, os navegadores webkit (chrome, safari) agora parecem usar uma base superior a 256. Talvez 2 16 , como o Opera? O IE e o Firefox ainda usam 256.


34
Importante: observe que o número 256 não está na especificação . Assim, esta resposta descreve um detalhe de implementação (reconhecidamente útil).
Matt Fenwick

6
Não apenas 256 não está na especificação como o @MattFenwick disse, mas também varia de acordo com a implementação. Aparentemente, é maior na Opera. No WeasyPrint e no cssselect, é "infinito": uso uma tupla de números inteiros em vez de um único inteiro.
Simon Sapin

3
@Faust ópera usa 16 bits em vez de 8
karlcow

4
Essa resposta tem uma descrição mais prática do que a resposta de Pekka, para ser sincero. Basicamente, o que o @Matt Fenwick diz: o que você está descrevendo é uma implementação prática da especificação. Uma falha nesse sentido, mas não em algo que deva ser feito, seja por autores ou implementadores.
BoltClock

7
256 parece insuficiente nas versões atuais do webkit (Chrome e Safari), reforçando ainda mais o argumento de @ MattFenwick.
Blazemonger

28

Boa pergunta.

Não sei ao certo - todos os artigos que consigo encontrar evitam o exemplo de várias classes, por exemplo, aqui -, mas presumo que, quando se trata de comparar a especificidade entre um seletor de classe e um ID , a classe é calculada com um valor de 15apenas, não importa quão detalhado seja.

Isso corresponde à minha experiência em como a especificidade se comporta.

No entanto, deve haver algum empilhamento de classes porque

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

é mais específico que

.o

a única explicação que tenho é que a especificidade das classes empilhadas é calculada apenas entre si, mas não com os IDs.

Atualização : eu meio que peguei agora. Não é um sistema de pontos, e as informações sobre as classes com peso de 15 pontos estão incorretas. É um sistema de numeração de 4 partes muito bem explicado aqui .

O ponto de partida é de 4 figuras:

style  id   class element
0,     0,   0,    0

De acordo com a explicação do W3C sobre a especificidade , os valores de especificidade para as regras acima mencionadas são:

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

este é um sistema de numeração com uma base muito grande (indefinida?).

Meu entendimento é que, como a base é muito grande, nenhum número na coluna 4 pode superar um número> 0 na coluna 3, o mesmo para a coluna 2, coluna 1 .... Isso está correto?

Eu estaria interessado em saber se alguém com uma melhor compreensão de matemática do que eu poderia explicar o sistema de numeração e como convertê-lo em decimal quando os elementos individuais forem maiores que 9.


Isso é porque está entre .o e .a .b etc. Portanto, eles seriam considerados coletivamente. Mas entre um ID e uma classe, por exemplo: .a e #a, o ID sempre prevalecerá. Suponho que apenas contará entre classes quando não houver um atributo mais avassalador. Por exemplo, classe passará por cima de elemento e id por cima de classe.
Sphvn

@ Ozaki é o que estou assumindo também, mas contradiz o que o OP está dizendo sobre o sistema de pontos. Deve haver mais em jogo. Eu gostaria de ver as regras por trás disso.
Pekka

Acabamos de perceber que ambos chegamos à mesma conclusão. Excelente trabalho!
Sam

5
Para o lado da matemática, podemos trabalhar na base 16 aqui (porque nenhum dos números individuais excede 15). Então 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240 256> 240 para que o seletor de ID ganhe.
Matthew Wilson

1
Sim, você pode pensar em cálculos de especificidade como sendo feitos em um sistema numérico com uma base grande. Eu acho que o termo "concatenar" (também usado nas especificações) é uma descrição muito melhor. (Vim aqui de responder a uma nova questão que acaba por ser um joguete de um presente, figura go ...)
BoltClock

9

O atual Rascunho de Trabalho dos Seletores Nível 4 faz um bom trabalho ao descrever a Especificidade no CSS:

As especificidades são comparadas comparando os três componentes em ordem: a especificidade com um valor A maior é mais específica; se os dois valores A estiverem vinculados, a especificidade com um valor B maior será mais específica; se os dois valores B também estiverem vinculados, a especificidade com um valor c maior é mais específica; se todos os valores estiverem vinculados, as duas especificações são iguais.

Isso significa que os valores A, B e C são completamente independentes um do outro.

15 classes não dão ao seu seletor uma pontuação de especificidade de 150, ele fornece um valor B de 15. Um único valor A é suficiente para superar isso.

Como metáfora, imagine uma família de 1 avô, 1 pai e 1 filho. Isso pode ser representado como 1,1,1 . Se o pai ou mãe tem 15 filhos, isso de repente não faz dele outro pai ( 1,2,0 ). Isso significa que os pais têm uma responsabilidade muito maior do que eles com apenas um filho ( 1,1,15 ). ;)

A mesma documentação também diz:

Devido a limitações de armazenamento, as implementações podem ter limitações no tamanho de A , B ou c . Nesse caso, valores maiores que o limite devem ser fixados nesse limite e não excedidos.

Isso foi adicionado para resolver o problema apresentado na resposta de Faust , em que as implementações de CSS em 2012 permitiram que os valores de especificidade transbordassem entre si.

Em 2012, a maioria dos navegadores implementava uma limitação de 255, mas essa limitação podia exceder. 255 classes tiveram uma especificidade A, B, c de 0,255,0 , mas 256 classes transbordaram e tiveram uma pontuação A, B, c de 1,0,0 . De repente, nosso valor B se tornou nosso valor A. A documentação dos seletores de nível 4 irradia completamente esse problema, afirmando que o limite nunca pode exceder. Com essa implementação, as classes 255 e 256 teriam a mesma pontuação A, B, c de 0,255,0 .

O problema dado na resposta de Faust já foi corrigido na maioria dos navegadores modernos.


8

Atualmente, estou usando o livro CSS Mastery: Advanced Web Standards Solutions .

O Capítulo 1, página 16, diz:

Para calcular a especificidade de uma regra, cada tipo de seletor recebe um valor numérico. A especificidade de uma regra é calculada somando o valor de cada um de seus seletores. Infelizmente, a especificidade não é calculada na base 10, mas um número de base alto e não especificado. Isso é para garantir que um seletor altamente específico, como um seletor de ID, nunca seja substituído por muitos seletores menos específicos, como seletores de tipo.

(ênfase minha) e

A especificidade de um seletor é dividida em quatro níveis constituintes: a, b, ce ed.

  • se o estilo for um estilo embutido, a = 1
  • b = o número total de seletores de identificação
  • c = o número de seletores de classe, pseudo-classe e atributo
  • d = o número de seletores de tipo e pseudoelementos

Continua dizendo que você pode fazer o cálculo frequentemente na base 10, mas apenas se todas as colunas tiverem valores menores que 10.


Nos seus exemplos, os IDs não valem 100 pontos; cada um vale [0, 1, 0, 0]pontos. Portanto, um ID supera 15 classes porque [0, 1, 0, 0]é maior do que [0, 0, 15, 0]em um sistema de números de base alta.


4

Gosto da comparação do ranking de especificidade com a tabela de medalhas dos Jogos Olímpicos (primeiro método de ouro - baseado primeiro no número de medalhas de ouro, depois prata e depois bronze).

Também funciona com sua pergunta (grande número de seletores em um grupo de especificidade). A especificidade considerou cada grupo separadamente. No mundo real, raramente vi casos com mais de uma dúzia de seletores).

Também há uma calculadora de especificidade bastante boa disponível aqui . Você pode colocar seu exemplo (#a e .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) lá e ver os resultados.

Exemplo da tabela de medalhas dos Jogos Olímpicos Rio 2016 insira a descrição da imagem aqui


3

Não acredito que a explicação do blog esteja correta. A especificação está aqui:

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

Os "pontos" de um seletor de classe não podem ser mais importantes do que um seletor de "id". Simplesmente não funciona assim.


Como eu disse na minha resposta. ^^ No entanto, faz diferença se você tiver mais do mesmo tipo (elemento, classe, id). Mas isso é bastante óbvio se o quinto diz o vermelho e o terceiro o azul, bem, vou ficar vermelho.
Sphvn

A redação em torno da especificidade provavelmente não mudou muito entre CSS2 e CSS2.1, mas você realmente deve apontar para a especificação CSS2.1 em discussões futuras, uma vez que substitui completamente o CSS2 que, em geral, estava quebrado no momento do lançamento.
Robin Whittleton

1

Eu diria que:

Element < Class < ID

Eu acho que eles só empilham dependendo do que você recebe se for múltiplo do mesmo. Portanto, uma Classe sempre substituirá o elemento e o ID sempre sobre a Classe, mas se estiver abaixo de qual dos 4 elementos em que 3 é azul e 1 é vermelho, será azul.

Por exemplo:

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

 .m .n .o
{
color blue;
}

Deve ficar vermelho.

Veja o exemplo http://jsfiddle.net/RWFWq/

"se as quintas disserem vermelho e as três disserem azul, vou ficar vermelha"

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.