Cuando trabajas con CSS durante cierto tiempo, es bastante habitual terminar con selectores cada vez más largos simplemente porque necesitas sobrescribir reglas anteriores con demasiada especificidad.
El problema aparece cuando acabas escribiendo selectores kilométricos o recurriendo constantemente a !important para conseguir que una propiedad aparentemente sencilla termine aplicándose.
La pseudoclase :where() de CSS te ofrece una forma especialmente elegante de evitar esta batalla porque permite crear selectores muy precisos sin aumentar su especificidad.
Gracias a esta característica puedes construir hojas de estilo más fáciles de sobrescribir, mantener y ampliar, algo especialmente interesante en proyectos grandes, temas de WordPress, plugins o sistemas de diseño.
¿Qué es la especificidad en CSS? 🎯
La especificidad CSS es uno de los criterios utilizados por el navegador para determinar qué declaración debe prevalecer cuando distintas reglas intentan modificar la misma propiedad de un elemento.
Un selector basado únicamente en elementos suele tener menos peso que uno que contiene una clase, mientras que utilizar un identificador mediante #id incrementa todavía más su especificidad.
Por ejemplo, estos tres selectores no tienen el mismo peso:
p {
color: black;
}
.texto {
color: blue;
}
#contenido .texto {
color: red;
}Aunque las tres reglas puedan terminar afectando al mismo párrafo, #contenido .texto tiene una especificidad considerablemente mayor que las otras dos.
Puedes profundizar en este funcionamiento consultando la explicación de especificidad CSS de MDN Web Docs.
¿Qué hace :where() en CSS? 🔎
La pseudoclase :where() permite agrupar o envolver selectores sin que los selectores incluidos dentro de sus paréntesis aporten especificidad.
Dicho de otra manera, todo aquello que escribas dentro de :where() tendrá una especificidad igual a cero a efectos del cálculo de esa parte del selector.
Observa este ejemplo:
:where(.contenido .articulo .texto) {
color: red;
}Aunque dentro de :where() aparecen tres clases diferentes, la especificidad aportada por ellas es 0-0-0.
Esta particularidad convierte a :where() en una herramienta extremadamente interesante cuando quieres seleccionar elementos de forma precisa sin crear reglas difíciles de sobrescribir.
La pseudoclase está incluida entre los selectores funcionales de CSS que puedes consultar en la documentación de pseudoclases de MDN.
Cómo reducir la especificidad de un selector con :where() 🛠️
Imagina que dentro de tu proyecto has terminado escribiendo este selector:
.contenido .articulo .cabecera h2 {
color: #333;
}El selector contiene tres clases y un elemento, por lo que sobrescribir posteriormente el color del encabezado puede obligarte a crear otra regla relativamente específica.
Puedes reducir drásticamente esa especificidad envolviendo las clases mediante :where():
:where(.contenido .articulo .cabecera) h2 {
color: #333;
}Ahora las tres clases situadas dentro de :where() no añaden especificidad, mientras que h2 continúa aportando la correspondiente al selector de elemento.
Para aplicar esta técnica correctamente puedes seguir estos pasos:
- 🔍 Identifica el selector cuya especificidad quieres reducir.
- 🧩 Localiza las clases, identificadores o combinaciones de selectores que solamente necesitas para delimitar dónde debe aplicarse la regla.
- ✍️ Introduce esos selectores dentro de
:where(). - 🎯 Mantén fuera de
:where()únicamente los selectores cuya especificidad quieras conservar. - 🧪 Comprueba el resultado utilizando las herramientas para desarrolladores del navegador.
- ✅ Intenta sobrescribir la regla mediante un selector sencillo para confirmar que has conseguido reducir correctamente su peso.
Ejemplo práctico de reducción de especificidad 💡
Supongamos que tienes un sitio web con la siguiente regla:
#principal .contenido .entrada a {
color: green;
}El problema principal es que el selector contiene un ID y dos clases, por lo que tiene bastante peso dentro de la cascada.
Si posteriormente quieres modificar los enlaces del footer podrías terminar necesitando algo innecesariamente complejo.
Una alternativa sería convertir la regla inicial en:
:where(#principal .contenido .entrada) a {
color: green;
}Los elementos situados dentro de :where() dejan de aportar especificidad y únicamente permanece la correspondiente al selector a.
Ahora puedes sobrescribir fácilmente ese enlace mediante:
.footer a {
color: blue;
}Has conseguido mantener una selección muy concreta en la primera regla sin convertirla en una barrera difícil de superar posteriormente.
Tabla resumen de especificidad con :where()
| Selector | Especificidad aproximada | Facilidad para sobrescribir |
|---|---|---|
p | 0-0-1 | Muy alta |
.texto | 0-1-0 | Alta |
.contenido .texto | 0-2-0 | Media |
#contenido .texto | 1-1-0 | Baja |
:where(.contenido .texto) | 0-0-0 | Muy alta |
:where(#contenido .texto) p | 0-0-1 | Muy alta |
:where(.contenido) .texto | 0-1-0 | Alta |
La tabla permite comprobar rápidamente que los selectores introducidos dentro de :where() dejan de aportar peso, mientras que aquellos situados fuera continúan formando parte del cálculo.
Diferencia entre :where() e :is() ⚖️
A primera vista :where() y :is() pueden parecer prácticamente iguales porque ambas pseudoclases permiten utilizar listas de selectores dentro de sus paréntesis.
Por ejemplo, puedes escribir:
:is(h1, h2, h3) {
margin-bottom: 20px;
}Y también:
:where(h1, h2, h3) {
margin-bottom: 20px;
}La diferencia fundamental está en que :where() siempre aporta especificidad cero, mientras que :is() toma en consideración la especificidad del selector más específico de su lista.
Por eso :where() resulta especialmente adecuado cuando tu objetivo consiste en mantener deliberadamente baja la especificidad de tus reglas CSS.
Cómo usar :where() con varios selectores 📦
Otra ventaja interesante es que puedes introducir diferentes alternativas dentro de una misma pseudoclase separándolas mediante comas.
Por ejemplo:
:where(article, section, .contenido) h2 {
margin-bottom: 1rem;
}Con esta regla puedes seleccionar los h2 situados dentro de cualquiera de esos elementos sin incrementar innecesariamente la especificidad correspondiente a los selectores incluidos en :where().
Esta sintaxis puede ayudarte a reducir duplicaciones y simplificar tu CSS cuando varios componentes necesitan compartir el mismo comportamiento.
Usar :where() en WordPress 🌐
La pseudoclase :where() puede resultar particularmente útil cuando trabajas con WordPress, donde es habitual encontrarse estructuras HTML con numerosas clases generadas por el tema, Gutenberg o diferentes plugins.
En lugar de crear una regla como esta:
.site-content .wp-block-group .wp-block-button .wp-block-button__link {
border-radius: 5px;
}Puedes reducir su especificidad utilizando:
:where(.site-content .wp-block-group .wp-block-button) .wp-block-button__link {
border-radius: 5px;
}De esta manera continúas delimitando perfectamente dónde debe aplicarse el estilo pero facilitas que otros estilos personalizados puedan modificarlo posteriormente.
Esta estrategia resulta especialmente valiosa cuando desarrollas un tema, un plugin o componentes reutilizables que otras personas tendrán que personalizar.
Evita abusar de !important 🚫
Uno de los síntomas más habituales de una hoja de estilos con demasiada especificidad es empezar a encontrar !important por todas partes.
Por ejemplo:
.boton {
background: red !important;
}Aunque !important puede tener usos legítimos, utilizarlo continuamente para superar selectores excesivamente específicos suele terminar creando una cadena de conflictos cada vez más complicada.
Reducir la especificidad desde el principio mediante :where() puede ayudarte a evitar gran parte de esas situaciones y conseguir una cascada mucho más predecible.
Cuándo conviene utilizar :where() ✅
:where() funciona especialmente bien cuando necesitas seleccionar un contexto concreto sin que dicho contexto aumente el peso de la regla.
Puedes plantearte utilizarla principalmente en estas situaciones:
- ✅ Cuando desarrollas componentes reutilizables que deberían ser fáciles de personalizar.
- ✅ Cuando creas estilos base que posteriormente pueden recibir modificaciones.
- ✅ Cuando necesitas utilizar selectores largos para delimitar una zona determinada del HTML.
- ✅ Cuando desarrollas temas o plugins de WordPress destinados a otros usuarios.
- ✅ Cuando estás intentando reducir el número de declaraciones con
!important. - ✅ Cuando quieres conseguir una arquitectura CSS más flexible y escalable.
Cuándo no necesitas :where() 🤔
No es necesario introducir :where() automáticamente en todos tus selectores, ya que un CSS sencillo basado en clases bien estructuradas normalmente puede mantenerse perfectamente sin ella.
Por ejemplo:
.tarjeta {
padding: 20px;
}En este caso la especificidad ya es suficientemente baja y envolver .tarjeta dentro de :where() probablemente no aportaría ninguna ventaja significativa.
La clave consiste en utilizar :where() cuando necesites precisión en la selección pero no quieras pagar esa precisión aumentando la especificidad.
Ventajas de reducir la especificidad con :where() 🚀
Una buena estrategia de especificidad consigue que modificar tu CSS meses después sea considerablemente más sencillo.
Al utilizar :where() correctamente obtienes selectores fáciles de sobrescribir, reduces la aparición de conflictos y evitas construir una escalada interminable de reglas cada vez más específicas.
También consigues que tus componentes sean más reutilizables, porque otro desarrollador puede personalizarlos utilizando selectores normales sin tener que estudiar previamente toda la estructura de tu hoja de estilos.
En proyectos grandes esta sencillez termina convirtiéndose en una ventaja importante para la mantenibilidad y escalabilidad del código CSS.
Conclusión 🏁
Aprender cómo reducir la especificidad de un selector con :where() te permite aprovechar mejor la cascada de CSS en lugar de luchar constantemente contra ella.
La idea fundamental es sencilla: todo selector incluido dentro de :where() aporta especificidad cero, mientras que los selectores que permanezcan fuera continúan contando normalmente.
Si utilizas esta pseudoclase para delimitar contextos, crear componentes reutilizables y mantener bajos los niveles de especificidad, conseguirás un CSS más limpio, predecible y fácil de modificar.
Antes de añadir otro selector todavía más largo o recurrir a !important, revisa si :where() puede ayudarte a resolver el problema desde su origen.


