This content is only available in Portuguese.
Also available in English.
CSS :where() e :is(): Especificidade, Resets e Manutenção
Muitos desenvolvedores ignoram as pseudo-classes CSS :where() e :is(), vendo-as como "syntax sugar". Este artigo revela como elas são cruciais para resolver o caos da especificidade, permitindo criar CSS escalável e manutenível. Entenda a diferença e aplique em resets, componentes e design systems.

Você já escreveu o mesmo bloco de CSS três vezes só mudando o seletor? Essa é exatamente a dor que
:is()e:where()resolvem — e a diferença entre os dois é mais importante do que parece.
Esse CSS te parece familiar:
header a,
footer a,
nav a {
color: blue;
text-decoration: none;
}Repetindo a mesma regra pra três contextos diferentes. Agora imagina que você tem dez contextos. E que cada um tem três variações de estado — :hover, :focus, :visited. O arquivo CSS vira uma lista telefônica.
O CSS moderno tem uma resposta pra isso. Duas, na verdade — e elas parecem iguais mas se comportam diferente num detalhe que vai te salvar de bugs sutis.
:is() — agrupe seletores sem repetição
O :is() aceita uma lista de seletores e aplica o estilo pra qualquer um que bater. O bloco acima vira:
:is(header, footer, nav) a {
color: blue;
text-decoration: none;
}Uma linha, mesmo resultado. O navegador interpreta isso exatamente como a versão repetida — semanticamente são equivalentes.
Fica mais interessante quando você combina com pseudo-classes:
/* Antes — repetindo pra cada estado */
button:hover,
button:focus,
button:active {
background: darkblue;
}
/* Depois — limpo */
button:is(:hover, :focus, :active) {
background: darkblue;
}Ou pra estilizar headings de uma vez:
/* Todos os headings dentro de article */
article :is(h1, h2, h3, h4) {
font-family: Georgia, serif;
line-height: 1.3;
}:where() — igualzinho, mas sem peso de especificidade
Aqui mora a diferença que importa.
Especificidade em CSS é o sistema de pontuação que decide qual regra vence quando duas se contradizem. Um seletor de ID vale mais que uma classe, que vale mais que uma tag. Quando você usa :is(), a especificidade do seletor mais forte dentro dos parênteses se propaga pra regra inteira.
/* :is() herda a especificidade do #header — alta */
:is(#header, .nav, footer) a {
color: blue;
}
/* ↑ esse seletor tem especificidade de ID
por causa do #header, mesmo que o elemento
seja .nav ou footer */O :where() funciona igual em comportamento — mas tem especificidade zero. Sempre. Não importa o que você colocar dentro.
/* :where() — especificidade zero */
:where(#header, .nav, footer) a {
color: blue;
}
/* ↑ fácil de sobrescrever — qualquer seletor
de classe ou tag já ganha */Na prática isso significa que :where() é ideal pra estilos base e resets — você define sem travar o desenvolvedor que vai customizar depois.
A diferença na vida real
Problema com :is()
/* base.css */
:is(article, section) p {
color: gray;
}
/* theme.css — não vai funcionar */
p {
color: black;
}
/* :is(article, section) p tem
especificidade maior que p */Solução com :where()
/* base.css */
:where(article, section) p {
color: gray;
}
/* theme.css — funciona */
p {
color: black;
}
/* :where() tem especificidade zero
qualquer p ganha na sobreposição */CSS reset moderno usa :where() por esse motivo. O Tailwind, o Open Props e vários resets populares usam :where() pra definir estilos base que nunca travam o desenvolvedor. A intenção é: "esse é o padrão, mas qualquer coisa sua sobrescreve facilmente."
Um exemplo que junta os dois
Num design system, você usaria os dois em camadas diferentes:
/* Camada base — :where() pra não travar ninguém */
:where(h1, h2, h3, h4, h5, h6) {
margin: 0 0 0.5em;
line-height: 1.2;
}
/* Camada de componente — :is() pra contextos específicos */
.card :is(h2, h3) {
font-size: 1.25rem;
color: var(--color-heading);
}
/* Estados interativos — :is() porque precisa de peso */
.btn:is(:hover, :focus-visible) {
outline: 2px solid currentColor;
outline-offset: 2px;
}Cuidado com seletores inválidos dentro do :is(). Se você colocar um seletor inválido numa lista separada por vírgula no CSS tradicional, a regra inteira é ignorada. Com :is() e :where(), seletores inválidos são silenciosamente descartados — os outros continuam funcionando. Isso é uma vantagem, mas pode esconder typos.
O que fica depois de ler isso
- :is() agrupa seletores e herda a especificidade do mais forte da lista.
- :where() faz o mesmo mas com especificidade zero — sempre sobrescrevível.
- Use :where() em resets e estilos base que não devem travar customização.
- Use :is() em componentes e estados de interação onde o peso importa.
- Os dois eliminam repetição de seletores — seu CSS fica menor e mais legível.
- Suporte nos navegadores: todos os modernos . Sem preocupação de compatibilidade.


