Especificidade

Podcast do CSS - 003: especificidade

Suponha que você esteja trabalhando com o seguinte HTML e CSS:

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

.branding {
  color: blue;
}

Há duas regras concorrentes aqui. Um deles vai deixar o botão vermelho, e o outro azul. Qual regra é aplicada ao elemento? Noções básicas sobre o algoritmo da especificação CSS sobre especificidade é a chave para entender como o CSS decide entre regras concorrentes.

A especificidade é um dos quatro estágios distintos da cascata, que foi abordado no último módulo, a cascata.

Pontuação de especificidade

Cada regra de seletor recebe uma pontuação. Pense na especificidade como uma pontuação total, e cada tipo de seletor gera pontos para essa pontuação. Vence o seletor com a maior pontuação.

Com especificidade em um projeto real, O equilíbrio é garantir que as regras de CSS que você espera aplicar, sejam aplicadas, ao mesmo tempo, mantendo as pontuações baixas para evitar complexidade. A pontuação deve ser tão alta quanto necessário, em vez de buscar a maior pontuação possível. No futuro, alguns CSSs realmente mais importantes talvez precisem ser aplicados. Se você alcançar a pontuação mais alta, isso deixará esse trabalho difícil.

Pontuação de cada tipo de seletor

Cada tipo de seletor gera pontos. Você soma todos esses pontos para calcular a especificidade geral de um seletor.

Seletor universal

Um seletor universal (*). não tem nenhuma especificidade e não recebe 0 pontos. Isso significa que qualquer regra com 1 ou mais pontos vai substituir essa

* {
  color: red;
}

Seletor de elemento ou pseudoelemento

Um elemento (tipo) ou pseudoelemento seletor recebe 1 ponto de especificidade .

Seletor de tipo

div {
  color: red;
}

Seletor de pseudoelemento

::selection {
  color: red;
}

Seletor de classe, pseudoclasse ou atributo

Uma classe, pseudoclasse ou o seletor de atributo recebe 10 pontos de especificidade.

Seletor de classe

.my-class {
  color: red;
}

Seletor de pseudoclasse

:hover {
  color: red;
}

Seletor de atributos

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

O :not() a própria pseudoclasse não acrescenta nada ao cálculo de especificidade. No entanto, os seletores transmitidos como argumentos são adicionados ao cálculo de especificidade.

div:not(.my-class) {
  color: red;
}

Esta amostra teria 11 pontos de especificidade porque ele tem um seletor de tipo (div) e uma classe dentro do :not().

Seletor de ID

Um ID seletor recebe 100 pontos de especificidade, desde que você use um seletor de ID (#myID) e não um seletor de atributo ([id="myID"]).

#myID {
  color: red;
}

Atributo de estilo inline

CSS aplicado diretamente ao atributo style do elemento HTML recebe uma pontuação de especificidade de 1.000 pontos. Isso significa que, para substituí-lo no CSS, você precisa escrever um seletor extremamente específico.

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

Regra !important

Por fim, um !important no final de um valor de CSS recebe uma pontuação de especificidade de 10.000 pontos. Essa é a maior especificidade que um item individual pode ter.

Uma regra !important for aplicada a uma propriedade CSS, para que os elementos na regra geral (seletor e propriedades) não recebam a mesma pontuação de especificidade.

.my-class {
  color: red !important; /* 10,000 points */
  background: white; /* 10 points */
}

Teste seu conhecimento

Teste seus conhecimentos sobre pontuação de especificidade

Qual é a pontuação de especificidade de a[href="#"]?

1
A a vale 1 ponto, mas a [href="#"] vale 10 pontos.
5
Tente novamente.
11
O a vale 1 ponto e o [href="#"] vale 10 pontos, totalizando 11 pontos.

Especificidade no contexto

A especificidade de cada seletor que corresponde a um elemento é somada. Considere este exemplo de HTML:

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

Este link tem duas classes. Adicione o seguinte CSS e ele terá um ponto de especificidade:

a {
  color: red;
}

Mencione uma das classes da regra ele agora tem 11 pontos de especificidade:

a.my-class {
  color: green;
}

Adicione a outra classe ao seletor, mas agora tem 21 pontos de especificidade:

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

Adicione o atributo href ao seletor ele agora tem 31 pontos de especificidade:

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

Por fim, adicione uma pseudoclasse :hover a tudo isso. o seletor termina com 41 pontos de especificidade:

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

Teste seu conhecimento

Teste seus conhecimentos sobre pontuação de especificidade

Qual dos seguintes seletores vale 21 pontos?

article > section
Os elementos valem 1 ponto, e há 2 elementos no seletor, o que equivale a 2 pontos.
article.card.dark
Os elementos valem 1 ponto, as classes valem 10 pontos e, com duas classes e um elemento, esse seletor vale 21 pontos.
article:hover a[href]
Os elementos valem 1 ponto, as pseudoclasses e os atributos valem 10 pontos, como há 2 pontos para os elementos e 20 pontos para os atributos e classes, esse seletor vale 22 pontos.

Visualização da especificidade

Em diagramas e calculadoras de especificidade, a especificidade costuma ser assim:

Um diagrama demonstrando os seletores mais específicos para os menos específicos

O grupo à esquerda é de seletores id. O segundo grupo são seletores de classe, atributo e pseudoclasse. O último grupo são os seletores de elemento e pseudoelemento.

Para referência, o seguinte seletor é 0-4-1:

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

Teste seu conhecimento

Teste seus conhecimentos sobre visualização de especificidade

Qual dos seletores a seguir é 1-2-1?

section#specialty.dark
Esse seletor é exibido como 1-1-1.
#specialty:hover li.dark
🎉
[data-state-rad].dark#specialty:hover
Esse seletor é exibido como 1-3-0.
li#specialty section.dark
Esse seletor é exibido como 1-1-2.

A especificidade está aumentando de forma pragmática

Vamos supor que temos um CSS parecido com este:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Com um HTML que se parece com:

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

O botão tem um fundo cinza, porque o segundo seletor ganha 11 pontos de especificidade (0-1-1). Isso ocorre porque ele tem um seletor de tipo (button), que é 1 ponto, e um seletor de atributo ([onclick]), que é 10 pontos.

A regra anterior, .my-button, recebe 10 pontos (0-1-0), porque ele tem um seletor de classe.

Se quiser turbinar essa regra, repita o seletor de classe desta forma:

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

button[onclick] {
  background: grey;
}

Agora, o botão terá um fundo azul, porque o novo seletor recebe uma pontuação de especificidade de 20 pontos (0-2-0).

Uma pontuação de especificidade correspondente vê a instância mais recente vencer

Vamos ficar com o exemplo do botão por enquanto e mudar o CSS para esta:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

O botão tem um fundo cinza, porque os dois seletores têm uma pontuação de especificidade idêntica (0-1-0).

Se você alternar as regras pela ordem de origem, o botão seria azul.

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

Essa é a única instância em que o CSS mais novo vence. Para isso, ele deve corresponder à especificidade de outro seletor que visa o mesmo elemento.

Recursos