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 conflitantes aqui. Um vai colorir o botão de vermelho e o outro de azul. Qual regra é aplicada ao elemento? Entender o algoritmo da especificação do CSS sobre especificidade é a chave para entender como o CSS decide entre regras concorrentes.

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

Pontuação de especificidade

Cada regra de seletor recebe uma pontuação. Você pode pensar na especificidade como uma pontuação total, e cada tipo de seletor ganha pontos em relação a essa pontuação. Vence o seletor com a maior pontuação.

Com a especificidade de um projeto real, o equilíbrio é garantir que as regras CSS que você espera aplicar sejam realmente aplicadas, mantendo as pontuações baixas para evitar complexidade. A pontuação precisa ser a mais alta possível, em vez de ter a maior pontuação possível. No futuro, pode ser necessário usar alguns CSS genuinamente mais importantes. Se você conseguir a pontuação mais alta, fará o trabalho difícil.

Pontuação de cada tipo de seletor

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

Seletor universal

Um seletor universal (*) não tem especificidade e recebe 0 pontos. Isso significa que qualquer regra com um ou mais pontos a substituirá

* {
  color: red;
}

Seletor de elemento ou pseudoelemento

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

Seletor de tipo

div {
  color: red;
}

Seletor de pseudoelementos

::selection {
  color: red;
}

Seletor de classe, pseudoclasse ou atributo

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

Seletor de classe

.my-class {
  color: red;
}

Seletor de pseudoclasse

:hover {
  color: red;
}

Seletor de atributo

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

A pseudoclasse :not() não adiciona 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;
}

Essa amostra teria 11 pontos de especificidade, porque tem um seletor de tipo (div) e uma classe dentro da :not().

Seletor de ID

Um seletor de ID 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

Quando aplicado diretamente ao atributo style do elemento HTML, o CSS recebe uma pontuação de especificidade de 1.000 pontos. Isso significa que, para fazer a substituição no CSS, é necessário criar um seletor extremamente específico.

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

Regra !important

Por fim, um !important ao final de um valor de CSS recebe uma pontuação de especificidade de 10.000 pontos. Essa é a especificidade mais alta que um item individual pode conseguir.

Uma regra !important é aplicada a uma propriedade CSS. Portanto, nada na regra geral (seletor e propriedades) não recebe 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 a pontuação de especificidade

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

1
O a vale 1 ponto, mas o [href="#"] vale 10 pontos.
5
Tente de novo.
11
a vale 1 ponto, e [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 CSS abaixo e ele vai ter um ponto de especificidade:

a {
  color: red;
}

Faça referência a uma das classes dessa regra, que agora tem 11 pontos de especificidade:

a.my-class {
  color: green;
}

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

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

Adicione o atributo href ao seletor, que 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 a pontuação de especificidade

Qual dos seguintes seletores vale 21 pontos?

article > section
Os elementos valem 1 ponto. Existem dois elementos no seletor, o que faz com que ele valha 2 pontos.
article.card.dark
Os elementos valem 1 ponto, as classes valem 10 pontos e, com 2 classes e 1 elemento, isso faz com que esse seletor valha 21 pontos.
article:hover a[href]
Os elementos valem 1 ponto, as pseudoclasses e os atributos valem 10 pontos, há 2 pontos para os elementos e 20 pontos para os atributos e as classes, faz com que esse seletor valha 22 pontos.

Como visualizar a especificidade

Em diagramas e calculadoras de especificidade, a especificidade geralmente é visualizada assim:

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

O grupo à esquerda são seletores de id. O segundo grupo são seletores de classe, atributo e pseudoclasse. O grupo final são seletores de elementos e pseudoelementos.

Para referência, o seletor a seguir é 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 seguintes seletores é 1-2-1?

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

Aumentando pragmaticamente a especificidade

Vamos supor que temos um CSS com a seguinte aparência:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Com HTML semelhante a este:

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

O botão tem um plano de 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 tem 10 pontos.

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

Se você quiser dar um impulso a 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 plano de fundo azul, porque o novo seletor recebe uma pontuação de especificidade de 20 pontos (0-2-0).

Uma pontuação de especificidade correspondente gera a vitória da instância mais recente

Vamos continuar com o exemplo do botão por enquanto e mudar o CSS para este:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

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

Se você alterar as regras na ordem de origem, o botão ficará azul.

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

Essa é a única situação em que o CSS mais recente prevalece. Para isso, ele precisa corresponder à especificidade de outro seletor que segmente o mesmo elemento.

Recursos