Selectores avanzados: :has(), :is(), :where() y :not()

Domina los selectores funcionales modernos para reducir duplicación, controlar especificidad y crear lógica visual sin JavaScript.

<code>:has()</code> permite seleccionar un elemento según su contenido o estado interno.

<code>:is()</code> y <code>:where()</code> agrupan selectores; <code>:where()</code> lo hace con especificidad 0.

<code>:not()</code> excluye casos concretos y evita reglas duplicadas.

Combinando estos selectores con estados como <code>:valid</code> y <code>:invalid</code> puedes resolver mucha lógica visual sin JavaScript.

  • Selecciona el elemento actual cuando se cumple una condición interna.
  • Durante años CSS no podía seleccionar un padre según su contenido. :has() resuelve eso y habilita patrones que antes requerían JavaScript.
  • La forma mental correcta es: elemento:has(condición). Si la condición se cumple, se estiliza el elemento principal.
  • En .card:has(img) no seleccionas la imagen, seleccionas la tarjeta por su contenido. En formularios, form:has(:invalid) permite feedback global de estado.
  • Sintaxis: elemento:has(selector).

:has() para decisiones de layout y estado

Selecciona el elemento actual cuando se cumple una condición interna.

Durante años CSS no podía seleccionar un padre según su contenido. :has() resuelve eso y habilita patrones que antes requerían JavaScript.

La forma mental correcta es: elemento:has(condición). Si la condición se cumple, se estiliza el elemento principal.

En .card:has(img) no seleccionas la imagen, seleccionas la tarjeta por su contenido. En formularios, form:has(:invalid) permite feedback global de estado.

  • Sintaxis: elemento:has(selector).
  • Casos típicos: tarjetas con/sin media, menús con submenú, formularios con errores.
  • Puedes combinar :has() con :not(): article:not(:has(img)).
  • Acota el alcance por componente: .checkout-form:has(:invalid) suele ser mejor que reglas globales.
  • Compatibilidad: soporte sólido en navegadores modernos; revisa Can I Use.

:is(), :where() y :not(): agrupar y excluir con estrategia

Mismo objetivo de mantenimiento, distinta estrategia de especificidad.

Usa :is() para agrupar selectores equivalentes sin repetir prefijos largos.

Usa :where() para estilos base que quieras sobrescribir con facilidad, porque su especificidad es 0.

Usa :not() para excluir variantes concretas sin duplicar reglas generales.

  • :is(a, b, ...): agrupa y toma la especificidad del argumento más fuerte.
  • :where(a, b, ...): agrupa con especificidad 0.
  • :not(...): exclusión explícita y mantenible.
  • Regla práctica: base con :where(), variaciones con clases de componente.

Estrategia de especificidad y buenas prácticas

Evita guerras de especificidad desde el diseño del selector.

Si una regla es fundacional (tipografía base, espaciados por defecto), prioriza :where() para permitir overrides claros.

Reserva :is() para agrupaciones dentro de componentes o layout, y combina con clases para estados de interfaz.

Evita cadenas muy complejas como :has(:not(...):is(...)) cuando no aportan valor real: la legibilidad también es mantenibilidad.

Pseudo-clases de validación en formularios

Estiliza inputs según required, pattern y validación nativa.

La validación nativa de HTML5 expone estados útiles para CSS: :valid, :invalid, :required y :optional.

Combinando esos estados con :has() puedes adaptar el botón de envío sin depender de JavaScript.

  • :valid / :invalid: según si el valor cumple las restricciones.
  • :required / :optional: según la presencia del atributo required.
  • Evita estilizar :invalid antes de interacción real; combina con :focus o :not(:placeholder-shown).
CSS
53

Selectores avanzados: :has(), :is(), :where() y :not()

Domina los selectores funcionales modernos para reducir duplicación, controlar especificidad y crear lógica visual sin JavaScript.

Código del tema: display: grid; gap: 1rem;

📘 Teoría

:has() para decisiones de layout y estado

Selecciona el elemento actual cuando se cumple una condición interna.

Durante años CSS no podía seleccionar un padre según su contenido. :has() resuelve eso y habilita patrones que antes requerían JavaScript.

La forma mental correcta es: elemento:has(condición). Si la condición se cumple, se estiliza el elemento principal.

En .card:has(img) no seleccionas la imagen, seleccionas la tarjeta por su contenido. En formularios, form:has(:invalid) permite feedback global de estado.

  • Sintaxis: elemento:has(selector).
  • Casos típicos: tarjetas con/sin media, menús con submenú, formularios con errores.
  • Puedes combinar :has() con :not(): article:not(:has(img)).
  • Acota el alcance por componente: .checkout-form:has(:invalid) suele ser mejor que reglas globales.
  • Compatibilidad: soporte sólido en navegadores modernos; revisa Can I Use.

:is(), :where() y :not(): agrupar y excluir con estrategia

Mismo objetivo de mantenimiento, distinta estrategia de especificidad.

Usa :is() para agrupar selectores equivalentes sin repetir prefijos largos.

Usa :where() para estilos base que quieras sobrescribir con facilidad, porque su especificidad es 0.

Usa :not() para excluir variantes concretas sin duplicar reglas generales.

  • :is(a, b, ...): agrupa y toma la especificidad del argumento más fuerte.
  • :where(a, b, ...): agrupa con especificidad 0.
  • :not(...): exclusión explícita y mantenible.
  • Regla práctica: base con :where(), variaciones con clases de componente.

Estrategia de especificidad y buenas prácticas

Evita guerras de especificidad desde el diseño del selector.

1

Si una regla es fundacional (tipografía base, espaciados por defecto), prioriza :where() para permitir overrides claros.

2

Reserva :is() para agrupaciones dentro de componentes o layout, y combina con clases para estados de interfaz.

3

Evita cadenas muy complejas como :has(:not(...):is(...)) cuando no aportan valor real: la legibilidad también es mantenibilidad.

Pseudo-clases de validación en formularios

Estiliza inputs según required, pattern y validación nativa.

La validación nativa de HTML5 expone estados útiles para CSS: :valid, :invalid, :required y :optional.

Combinando esos estados con :has() puedes adaptar el botón de envío sin depender de JavaScript.

  • :valid / :invalid: según si el valor cumple las restricciones.
  • :required / :optional: según la presencia del atributo required.
  • Evita estilizar :invalid antes de interacción real; combina con :focus o :not(:placeholder-shown).

🧭 Visuales clave

Selectores avanzados y prioridad

Ayuda a decidir cuando conviene simplificar selectores para mantener override limpio.

Comparativa de selectores compuestos y su impacto en especificidad.

Mapa de selectores avanzados

Sirve como chuleta rápida para reconocer combinadores, funcionales y contextos donde aportan precisión real.

Resumen visual de selectores avanzados en CSS y sus casos de uso

Pseudo-clases y pseudo-elementos

Aclara una de las confusiones más frecuentes cuando ya empiezas a usar selectores más expresivos.

Comparativa entre pseudo-clases y pseudo-elementos en CSS

🧪 Aprende probando

Ejemplo Demo: decisiones con :has() + agrupación con :is() Activa un modo visual y comprueba estilos compartidos sin duplicar selectores.
⌄
Ejemplo Demo interactiva: formulario contextual El contenedor cambia cuando hay foco o errores.
⌄

🏁 Retos

Reto Reto: form con :has(:invalid) Deshabilita visualmente el botón cuando haya campos inválidos usando form:has(:invalid) .btn-submit.
⌄
Reto Reto: exclusión con :not() Aplica un estilo neutro a todos los botones salvo primary y danger.
⌄
Reto Reto: tarjeta condicional Resalta .card solo si contiene una imagen.
⌄

🧰 Recursos

¿Qué es esto?

Soy Cristian Eslava y a veces hago webs para procrastinar yo y vosotros. culTest

La hice en febrero de 2026 para facilitar el aprendizaje de mis alumnos. La idea es aprender desarrollo web practicando y que el proyecto siga creciendo con nuevos temas, tests y retos.

Está inspirada en MDN, W3Schools, CodePen, Manz y muchos otros sitios de documentación sobre desarrollo web. Quería combinar teoría útil, ejemplos ejecutables, retos y el sistema de tests que ya tenía en culTest. culTest

Si te gustó, si no te gustó o si quieres escribirme, puedes hacerlo en cristianeslava@gmail.com