:has() en CSS: el selector padre que pedimos durante 20 años (y 6 cosas que ya hago con él)
sin JavaScript, sin clases extra, sin trucos raros
Contents
Durante años la respuesta a "¿se puede seleccionar el padre en CSS?" fue "no, usa JavaScript". Ya no. :has() funciona en todos los navegadores modernos desde finales de 2023 (Firefox fue el último, en la versión 121) y yo ya lo uso en producción sin miedo.
La idea: A:has(B) selecciona A si adentro tiene algo que cumpla B. Van mis usos favoritos:
1. Tarjetas con o sin imagen
.card:has(img) {
grid-template-rows: 180px 1fr;
}
.card:not(:has(img)) {
padding-top: 2rem;
}
2. Estilos de error en formularios, sin JS
.campo:has(input:user-invalid) label {
color: #b91c1c;
}
.campo:has(input:user-invalid) .ayuda {
display: block;
}
Ojo: :user-invalid y no :invalid. La diferencia es que :user-invalid solo aplica después de que el usuario interactuó con el campo. Con :invalid el formulario aparece en rojo antes de que escribas nada, y eso es horrible.
3. Bloquear el scroll cuando hay un modal abierto
body:has(dialog[open]) {
overflow: hidden;
}
Adiós al useEffect que agregaba y quitaba una clase al body.
4. Modo oscuro con un checkbox, cero JS
:root:has(#modo-oscuro:checked) {
color-scheme: dark;
--fondo: #111;
--texto: #eee;
}
(Para guardar la preferencia sí necesitas JS, pero el cambio visual no.)
5. Cambiar el layout según cuántos hijos hay
.galeria {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.galeria:has(> :nth-child(5)) {
grid-template-columns: repeat(3, 1fr);
}
Si existe un quinto hijo, es que hay 5 o más, y pasamos a 3 columnas.
6. El hermano anterior
li:has(+ li:hover) {
transform: scale(1.05);
}
Esto selecciona el li que está justo ANTES del que tiene hover. Durante años fue imposible. Lo uso para un efecto tipo dock de macOS en un menú.
Cuidado con
- No lo pongas en selectores súper amplios tipo
*:has(...)en un DOM gigante. Los navegadores lo optimizan bien, pero no abuses - Si necesitas soportar navegadores viejos, envuélvelo en
@supports selector(:has(*))
¿Qué otros usos le han encontrado? Quiero robarles ideas jaja 💜
Written by
Sofía Ramírez
Frontend dev 💜 React, TypeScript y mucho café de olla. Trabajo remoto para una empresa gringa desde Guadalajara. Fundé codigo_en_espanol porque todo está en inglés y ya me cansé jaja
Get the best of #codigo_en_espanol weekly
One email each Monday with the most useful posts. No spam; unsubscribe in one click.
Comments
Sign in to join the conversation.
Sign in to comment