Calculadora de Especificidade CSS

Calcule a especificidade CSS de qualquer seletor. Decomposição colorida, comparação múltipla, suporta :is, :not, :has, :where conforme W3C.

Seletores CSS (um por linha)
Um seletor por linha. Regras separadas por vírgula contam como uma linha de entrada.
Referência de Especificidade
ComponenteExemplosPeso
a IDs#header, #main(1, 0, 0)
b Classes / Atributos / Pseudo-classes.btn, [type="text"], :hover, :nth-child(2)(0, 1, 0)
c Tipos / Pseudo-elementosdiv, p, ::before, ::placeholder(0, 0, 1)
*, :where(...), +, >, ~(0, 0, 0)
:is(A, B), :not(A), :has(A)max do argumento

Calculadora de Especificidade CSS — Analise Seletores, Calcule (a, b, c)

Cole qualquer seletor CSS — simples ou composto, com combinadores, pseudo-classes, pseudo-elementos, ou os modernos :is/:not/:where/:has — e a calculadora retorna a tripla de especificidade W3C. A decomposição mostra a qual componente cada token contribui, e uma vista de comparação classifica vários seletores para você ver de relance qual regra vence a cascata.

O que é especificidade CSS em um parágrafo?

Quando duas regras CSS tentam definir a mesma propriedade no mesmo elemento, o navegador precisa de um critério de desempate. O primeiro é *origem e importância* (user-agent < autor < usuário, depois !important inverte). Em seguida, *especificidade*: cada seletor recebe um peso, expresso em três números — (a, b, c) — e a tupla maior vence, comparando da esquerda para a direita.

Os três slots contam:

- **a** — número de seletores ID (`#foo`)
- **b** — número de seletores de classe (`.bar`), atributo (`[type=text]`), e pseudo-classes (`:hover`)
- **c** — número de seletores de tipo (`div`) e pseudo-elementos (`::before`)

Um seletor como `#nav .item a:hover` tem um ID, duas entradas classe/pseudo-classe, e um tipo — especificidade (1, 2, 1). Vence `.menu .item a:focus` (0, 3, 1) porque o primeiro slot ganha independente de quão altos sejam os slots posteriores.

Como `:is()`, `:not()`, e `:has()` afetam a especificidade?

Os três contribuem com a especificidade *máxima* dos seus argumentos, não zero, não a soma.

Exemplo:

```
:is(.btn, #primary) { color: red; }
```

A especificidade é determinada por `#primary` (1, 0, 0), não por `.btn` (0, 1, 0). O token completo `:is(...)` contribui (1, 0, 0).

A mesma regra aplica a `:not(...)` e `:has(...)` — eles pegam o seletor mais pesado dentro dos parênteses. Por isso `:not(#admin)` é um seletor pesado apesar de parecer inocente; é especificidade (1, 0, 0) sozinho.

Este comportamento está definido em CSS Selectors Level 4. O `:not()` antigo (Level 3, forma simples de um seletor único) seguia a mesma regra, então a maioria dos navegadores sempre concordou.

E `:where(...)`?

`:where(...)` é a válvula de escape: contribui **especificidade zero** independente do que contenha.

```
:where(#header, .nav, h1) { color: blue; }
```

Especificidade = (0, 0, 0). Isto é intencional. `:where()` permite escrever um estilo base que seletores agrupados compartilham sem bloquear futuras sobrescritas — qualquer coisa que mire os mesmos elementos com nem que seja uma classe vai vencer.

Um padrão comum é envolver regras de reset ou padrão em `:where(...)` para que elas tenham efetivamente nenhum peso de especificidade, enquanto estilos de componente autorais ficam livres para sobrescrevê-las com seletores normais. Adicionado em CSS Selectors Level 4 (2018) e entregue em todos os navegadores evergreen até 2021.

Por que às vezes vejo `(a, b, c, d)` com quatro slots?

Artigos antigos adicionam um quarto slot no início para **estilo inline** (o atributo `style="..."`), dando (1, 0, 0, 0) para qualquer declaração inline. O W3C tirou isso da tupla formal de especificidade porque o estilo inline é uma camada de origem separada — ele vence todas as decisões de cascata no nível autor antes mesmo da especificidade ser comparada.

Na prática:

1. Declarações `!important` vencem (camada de origem).
2. Estilo inline vence qualquer seletor sem `!important`.
3. Seletores são então classificados por (a, b, c) — IDs, classes/attrs/pseudo-classes, tipos/pseudo-elementos.
4. Se a especificidade empata, a regra declarada por último em ordem de fonte vence.

Esta calculadora segue a convenção moderna de três slots. Se comparando com um tutorial mais antigo, preencha mentalmente com um 0 inicial — `(0, 1, 2, 1)` e `(1, 2, 1)` descrevem o mesmo seletor.

O seletor universal `*` ou combinadores adicionam especificidade?

Não. Nada do seguinte contribui para a especificidade:

- `*` (seletor universal)
- ` ` (combinador de descendente, escrito como espaço)
- `>` (combinador de filho)
- `+` (combinador de irmão adjacente)
- `~` (combinador de irmão geral)
- `||` (combinador de coluna, para tabelas — Level 4)

Um seletor como `* > * + *` tem especificidade (0, 0, 0) — três universais e dois combinadores, todos sem peso. Combinadores descrevem *relações*, não o que está sendo selecionado, então não adicionam peso.

É por isso que `body > main p` (0, 0, 3) empata com `h1 ~ h2 ~ p` (0, 0, 3) — mesmos três seletores de tipo, combinadores diferentes, mesma especificidade. A cascata decide então por ordem de fonte.

Qual a diferença entre pseudo-classes e pseudo-elementos?

**Pseudo-classes** descrevem um estado de um elemento:

- `:hover`, `:focus`, `:active`, `:checked`, `:disabled`
- `:nth-child(2)`, `:nth-of-type(odd)`, `:first-child`
- `:lang(en)`, `:dir(rtl)`, `:state(custom)`

Contribuem para o slot **b** — mesmo peso que um seletor de classe.

**Pseudo-elementos** descrevem uma sub-parte virtual de um elemento:

- `::before`, `::after`, `::first-line`, `::first-letter`
- `::placeholder`, `::marker`, `::backdrop`, `::selection`

Contribuem para o slot **c** — mesmo peso que um seletor de tipo.

A diferença sintática é dois-pontos único (`:hover`) vs dois-pontos duplo (`::before`). CSS2 usava dois-pontos único para os quatro pseudo-elementos mais antigos (`:before`, `:after`, `:first-line`, `:first-letter`) — esta calculadora aceita ambas formas e classifica esses quatro como pseudo-elementos em qualquer caso.

Como reduzo a especificidade quando estou em guerra com outra folha de estilos?

Várias técnicas em severidade crescente:

1. **Use `:where()`** — envolva as partes pesadas do seu seletor em `:where()` para que não contribuam nada. `:where(.legacy) .button` → (0, 1, 0) em vez de (0, 2, 0). Melhor para folhas reset.
2. **Tire IDs dos seletores** — refatore `#nav .item` para `.nav .item` se o markup permitir. IDs são o contribuinte mais pesado sozinho.
3. **Use uma única classe** — seletores planos como `.btn-primary` vencem porque empatam em (0, 1, 0) contra a maioria dos estilos autorais, deixando a ordem de fonte decidir.
4. **Duplique uma classe** — `.btn.btn` (0, 2, 0) é um hack conhecido para aumentar a especificidade *sem* precisar de IDs.
5. **Use cascade layers** — `@layer base, components, utilities;` permite controlar qual arquivo vence independente da especificidade. A camada declarada depois vence, ponto.
6. **Use `!important`** — último recurso. Funciona mas cria uma cadeia frágil de guerras de sobrescrita.

A estratégia moderna é: minimizar especificidade em CSS de componente (classes únicas), envolver regras legacy/reset em `:where()`, e usar cascade layers para a divisão tooling/utility.

Esta calculadora é privada e offline?

Sim. Tudo é calculado localmente no navegador por algumas centenas de linhas de JavaScript:

- O parser de seletores é escrito à mão, sem nenhum engine CSS externo chamado.
- Sem telemetria, sem analytics para os cálculos em si.
- O botão Exemplos preenche o textarea com strings embutidas; nada é baixado.
- A página compartilha os assets normais do site (Bootstrap CSS, ícones) mas nenhuma API de terceiros é contatada para a matemática real de especificidade.

Você pode verificar abrindo DevTools → Rede e observando enquanto digita ou clica em Calcular — nenhuma requisição deveria disparar. Isso também significa que a calculadora funciona offline depois que a página carrega, útil se estiver auditando uma folha de estilos em voo ou em zona com sinal fraco.

Recursos Principais

  • Tupla (a, b, c) correta segundo W3C para qualquer seletor CSS
  • Decomposição colorida destacando qual token contribui para cada slot
  • Vista de comparação multi-seletor, ordenada por especificidade decrescente
  • Manuseio correto de :is(), :not(), :has() — especificidade max do argumento
  • :where(...) reconhecido como especificidade zero
  • Pseudo-elementos (::before, ::after, ::first-line) classificados separadamente de pseudo-classes
  • Pseudo-elementos CSS2 com dois-pontos único (:before, :after) aceitos
  • Seletor universal * e combinadores (>, +, ~, espaço) corretamente com peso zero
  • Seletores de atributo, incluindo [attr=value] e [attr^=value]
  • Pseudo-classes funcionais :nth-child(), :nth-of-type(), :lang(), :dir()
  • Preset Exemplos carrega 10 seletores representativos para comparação instantânea
  • Detecção de empate — destaca seletores com mesma especificidade
  • JavaScript puro, sem engine CSS externo
  • Funciona offline após o primeiro carregamento
  • 100% no cliente — seus seletores ficam no seu navegador