Más aplicaciones del mundo real para :has() | trucos CSS
Él :has()
pseudo-clase es, por supuesto, mi nueva característica favorita de CSS. Sé que lo es para muchos de ustedes también, al menos aquellos de ustedes que participaron en la encuesta Estado de CSSSer capaz de escribir selectores al revés nos da más superpoderes que nunca creí posibles.
Digo "más superpoderes" porque ya hay un montón de ideas inteligentes realmente sorprendentes publicadas por un grupo de personas súper inteligentes, como:
Este artículo no es una guía definitiva para :has()
. Tampoco aquí para repetir lo que ya se ha dicho. Solo yo (hola 👋) apareciendo por un momento para compartir algunas de las formas que probablemente usaré :has()
en mi trabajo diario... es decir, una vez que sea compatible oficialmente con Firefox que está por venir.
Cuando eso suceda, puedes apostar que comenzaré a usarlo. :has()
En todas partes. Estos son algunos ejemplos del mundo real de cosas que creé recientemente y pensé: "Dios, esto va a ser mucho mejor por una vez". :has()
totalmente respaldado.”
Evite llegar fuera de su componente de JavaScript
¿Alguna vez ha creado un componente interactivo que a veces necesita afectar los estilos en algún otro lugar de la página? Tome el siguiente ejemplo donde <nav>
es un mega menú y al abrirlo cambia los colores de <header>
contenido por encima de él.
Siento que debo hacer tal cosa. Todo el tiempo.
Este ejemplo particular es un componente React que hice para un sitio. Tuve que "llegar más allá" de la parte Reaccionar de la página con document.querySelector(...)
y cambiar de clase a <body>
, <header>
u otro componente. No es el fin del mundo, pero seguro que se siente un poco asqueroso. Incluso en un sitio completamente React (por ejemplo, un sitio Next.js), tendré que elegir entre administrar el menuIsOpen
apunte mucho más arriba en el árbol de componentes, o haga la misma selección en un elemento DOM, que no es muy React-y.
con :has()
el problema desaparece:
header:has(.megamenu--open) {
/* style the header differently if it contains
an element with the class ".megamenu--open"
*/
}
¡No más lidiar con otras partes del DOM en mis componentes de JavaScript!
Mejor UX para rayas de mesa
Agregar "franjas" alternas a sus tablas puede ser una buena mejora de la interfaz de usuario. Ayudan a sus ojos a realizar un seguimiento de la fila en la que se encuentra mientras escanea la tabla.
Pero en mi experiencia, esto no funciona bien en mesas con solo dos o tres filas. Si tiene, por ejemplo, una tabla con tres filas en <tbody>
y usted "alinea" cada fila "par", puede terminar con una sola raya. Esto realmente no vale un modelo y puede dejar a los usuarios preguntándose qué tiene de especial esta fila resaltada.
Usando esta técnica donde Brahms usó :has()
para aplicar estilos basados en el número de hijospodemos aplicar franjas tabulares cuando hay más de, digamos, tres filas:
También puede decidir hacer esto solo si la tabla tiene al menos un cierto número de columnas:
table:has(:is(td, th):nth-child(3)) {
/* only do stuff if there are three or more columns */
}
Eliminar la lógica de clase condicional de las plantillas
A menudo tengo que cambiar el diseño de una página dependiendo de lo que hay en la página. Tome el siguiente diseño de cuadrícula, donde la ubicación del contenido principal cambia las áreas de la cuadrícula dependiendo de si hay una barra lateral disponible.
Esto es algo que puede depender de si hay páginas relacionadas configuradas en el CMS. Normalmente haría esto con la lógica de la plantilla para agregar condicionalmente clases de modificador BEM al contenedor de diseño para tener en cuenta ambos diseños. Este CSS podría verse así (las reglas de respuesta y otras cosas se omiten por brevedad):
/* m = main content */
/* s = sidebar */
.standard-page--with-sidebar {
grid-template-areas: 's s s m m m m m m m m m';
}
.standard-page--without-sidebar {
grid-template-areas: '. m m m m m m m m m . .';
}
Desde una perspectiva de CSS, esto está perfectamente bien, por supuesto. Pero hace que el código de la plantilla sea un poco desordenado. Dependiendo de su lenguaje de plantillas, puede ser bastante feo agregar condicionalmente un montón de clases, especialmente si también tiene que hacer esto con muchos elementos secundarios.
Compara esto con un :has()
enfoque basado en:
/* m = main content */
/* s = sidebar */
.standard-page:has(.sidebar) {
grid-template-areas: 's s s m m m m m m m m m';
}
.standard-page:not(:has(.sidebar)) {
grid-template-areas: '. m m m m m m m m m . .';
}
Honestamente, no es mucho mejor desde la perspectiva de CSS, pero eliminar las clases de modificadores condicionales de la plantilla HTML es una buena victoria si me preguntas.
Es fácil pensar en soluciones de microdiseño :has()
— como un mapa cuando hay una imagen en él — pero creo que también será muy útil para esos cambios de diseño macro.
Mejor control de la especificidad
Si leyó mi último artículo, sabrá que soy muy exigente con la especificidad. Si, como yo, no desea que sus puntajes de especificidad se inflen cuando se agregan :has()
y :not()
en sus estilos, asegúrese de usar :where()
.
Esto se debe a que los detalles de :has()
está basado en el elemento más específico en su lista de argumentosEntonces, si tiene algo como una identificación allí, su selector será difícil de anular en la cascada.
Por otra parte, la especificidad de :where()
siempre es cero, nunca se suma a la puntuación de especificidad.
/* specificity score: 0,1,0.
Same as a .standard-page--with-sidebar
modifier class
*/
.standard-page:where(:has(.sidebar)) {
/* etc */
}
El futuro es brillante
Estas son solo algunas cosas que no puedo esperar para poder usar en producción. El CSS-Tricks Almanac también tiene un montón de ejemplos. ¿Qué esperas hacer con :has()
¿Qué ejemplos del mundo real has encontrado donde :has()
sería la solución ideal?
Deja una respuesta