Este contenido solo está disponible en Portugués.

También disponible en Español.

Ver traducción
Frontend

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.

Equipe Blueprintblog5 min
CSS :where() e :is(): Especificidade, Resets e Manutenção

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:

text
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:

text
: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:

text
/* 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:

text
/* 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.

text
/* :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.

text
/* :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:

text
/* 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.

Etiquetas del articulo

Articulos relacionados

Recibe los ultimos articulos en tu correo.

Follow Us: