Este conteúdo está disponível apenas em Espanhol.
Também está disponível em Português.
CSS :where() y :is(): Especificidad, Resets y Mantenimiento
Muchos desarrolladores ignoran las pseudo-clases CSS :where() e :is(), viéndolas como "azúcar sintáctico". Este artículo revela cómo son cruciales para resolver el caos de la especificidad, permitiendo crear CSS escalable y mantenible. Entiende la diferencia y aplícala en resets, componentes y sistemas de diseño.

¿Ya has escrito el mismo bloque de CSS tres veces solo cambiando el selector? Ese es exactamente el problema que
:is()y:where()resuelven — y la diferencia entre ambos es más importante de lo que parece.
Este CSS te resulta familiar:
header a,
footer a,
nav a {
color: blue;
text-decoration: none;
}Repitiendo la misma regla para tres contextos diferentes. Ahora imagina que tienes diez contextos. Y que cada uno tiene tres variaciones de estado — :hover, :focus, :visited. El archivo CSS se convierte en una guía telefónica.
El CSS moderno tiene una respuesta para esto. Dos, de hecho — y parecen iguales pero se comportan diferente en un detalle que te salvará de errores sutiles.
:is() — agrupa selectores sin repetición
El :is() acepta una lista de selectores y aplica el estilo a cualquiera que coincida. El bloque anterior se convierte en:
:is(header, footer, nav) a {
color: blue;
text-decoration: none;
}Una línea, mismo resultado. El navegador lo interpreta exactamente como la versión repetida — semánticamente son equivalentes.
Se vuelve más interesante cuando lo combinas con pseudo-clases:
/* Antes — repetindo pra cada estado */
button:hover,
button:focus,
button:active {
background: darkblue;
}
/* Depois — limpo */
button:is(:hover, :focus, :active) {
background: darkblue;
}O para estilizar encabezados de una vez:
/* Todos os headings dentro de article */
article :is(h1, h2, h3, h4) {
font-family: Georgia, serif;
line-height: 1.3;
}:where() — idéntico, pero sin peso de especificidad
Aquí reside la diferencia importante.
La especificidad en CSS es el sistema de puntuación que decide qué regla prevalece cuando dos se contradicen. Un selector de ID vale más que una clase, que vale más que una etiqueta. Cuando usas :is(), la especificidad del selector más fuerte dentro de los paréntesis se propaga a toda la regla.
/* :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 */El :where() funciona igual en comportamiento — pero tiene especificidad cero. Siempre. No importa lo que pongas dentro.
/* :where() — especificidade zero */
:where(#header, .nav, footer) a {
color: blue;
}
/* ↑ fácil de sobrescrever — qualquer seletor
de classe ou tag já ganha */En la práctica, esto significa que :where() es ideal para estilos base y resets — defines sin bloquear al desarrollador que personalizará después.
La diferencia en la vida real
Problema con :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 */Solución con :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 */El reset CSS moderno usa :where() por esta razón. Tailwind, Open Props y varios resets populares usan :where() para definir estilos base que nunca bloquean al desarrollador. La intención es: "este es el estándar, pero cualquier cosa tuya lo sobrescribe fácilmente."
Un ejemplo que une ambos
En un sistema de diseño, usarías ambos en capas 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 con los selectores inválidos dentro de :is(). Si colocas un selector inválido en una lista separada por comas en CSS tradicional, la regla entera se ignora. Con :is() y :where(), los selectores inválidos se descartan silenciosamente — los otros siguen funcionando. Esto es una ventaja, pero puede ocultar errores tipográficos.
Lo que queda después de leer esto
- :is() agrupa selectores y hereda la especificidad del más fuerte de la lista.
- :where() hace lo mismo pero con especificidad cero — siempre sobrescribible.
- Usa :where() en resets y estilos base que no deben bloquear la personalización.
- Usa :is() en componentes y estados de interacción donde el peso importa.
- Ambos eliminan la repetición de selectores — tu CSS es más pequeño y legible.
- Soporte en navegadores: todos los modernos. Sin preocupación de compatibilidad.


