El CSS: tiene selector (y más de 4 ejemplos)

El :hasselector CSS le ayuda a seleccionar elementos que contienen elementos que coinciden con el selector que pasa a la :has()función. Es esencialmente un selector “principal”, aunque mucho más útil que eso. Por ejemplo, imagina poder seleccionar todos divlos correos electrónicos pero solo cuando contienen un archivo p. Eso es lo que podemos hacer:

div:has(p) {  background: red;}/*  div !-- selected! --     p/p  div  div/div !-- not selected --  div !-- not selected --    section/section  /div*/

Aunque no es compatible con ningún navegador mientras escribe, ahora se incluye en Safari Technical Preview 137, ¡así que está empezando a suceder!

¡Muy útil, verdad! Aquí hay otro ejemplo. Digamos que quieres espacio después de tus encabezados. ¡Por supuesto! Un poco de margin-block-endtu h2deberías hacerlo. Pero… ¿y si hay subtítulo? Ahora podemos seleccionar un padre con la condición de que haya un subtítulo presente y ajustar el espacio.

h2,.subtitle {  margin: 0 0 1.5rem 0;}.header-group:has(h2):has(.subtitle) h2 {  margin: 0 0 0.2rem 0; /* reduce spacing on header, because subtitle will handle it */}/*  div    h2Blog Post Title/h2 !-- main spacing applied here --  /div  div    h2Blog Post Title/h2    div !-- main spacing applied here --      This is a subtitle    /div  /div*/

Mi forma de pensar :hases la siguiente: es una pseudoclase de selector principal . Eso en CSS significa “te permite cambiar el elemento principal si tiene un elemento secundario u otro elemento que lo sigue”. ¡Esto puede parecer extraño! Podrías romper tu modelo mental de cómo funciona CSS. Así es como estoy acostumbrado a pensar en CSS:

.parent .child {  color: red;}

Sólo puede reducir el estilo de padre a hijo, pero nunca hacer una copia de seguridad del árbol. :hasEsto cambia completamente porque hasta ahora no ha habido selectores principales en CSS y hay algunas buenas razones para ello. Debido a la forma en que los navegadores analizan HTML y CSS, seleccionar el padre si se cumplen ciertas condiciones podría generar todo tipo de problemas de rendimiento.

Si me siento y pienso en todas las formas en que podría consumir :hashoy en día, me duele la cabeza. Abriría esta caja de Pandora de oportunidades que nunca han sido posibles solo con CSS.

Otro ejemplo: digamos que queremos aplicar estilos solo a enlaces que contienen imágenes:

a:has( img) {  border: 20px solid white;}

Esto sería útil de vez en cuando. También veo :hasque se usa para agregar margen y relleno condicionalmente a elementos según su contenido. Eso sería genial.

El :hasselector es parte de la especificación CSS Selectors Level 4, :notque es la misma especificación que tiene la pseudoclase extremadamente útil.


Se podría argumentar que el :hasselector CSS es más poderoso que simplemente un selector “principal”, ¡que es exactamente lo que ha hecho Bramus! Como en el ejemplo de subtítulos anterior, en última instancia no necesariamente selecciona el elemento principal, puede seleccionar el elemento principal en una condición has, pero luego, en última instancia, selecciona un elemento secundario desde allí.

/*  Matches figure elements that have a figcaption as a child element */figure:has(figcaption) { … }/* Matches img elements that is a child of a figure that contains a figcaption child element */figure:has(figcaption) img { … }

Allí puede ver rápidamente que el segundo selector está seleccionando un hijo img, no sólo el padre del archivo figcaption.

Lista de selectores

Puedes encadenarlo:

article:has(h2):has(ul) {}

O dale una lista de selección:

article:has(h2, ul) {}

Y la lista es indulgente: la lista ya no es “indulgente” después de que el W3C adoptó una resolución en diciembre de 2020 en respuesta a un problema reportado. Entonces, si la lista de selección contiene incluso un argumento no válido, se ignora toda la lista:

/*   */article:has(h2, ul, ::-blahdeath) {  /* ::blahdeath is invalid, making the entire selector invalid. */}

Una solución alternativa es anidar un selector más indulgente allí, como :is()o :where():

/*   */article:has(:where(h2, ul, ::-blahdeath)) {  /* :where is a forgiving selector, making this valid. */}

Pruebas de soporte

@supports(selector(:has(p))) {  /* Supported! */}

El :not()selector es parte de la misma especificación…

A diferencia de :has, :nottiene un soporte de navegador bastante decente y lo uso por primera vez el otro día:

ul li:not(:first-of-type) {  color: red;}

Eso es genial. También me encanta lo jodidamente legible que es; No es necesario haber visto nunca esta línea de código para comprender lo que hace.

Otra forma que puedes utilizar :notes para los márgenes:

ul li:not(:last-of-type) {  margin-bottom: 20px;}

Entonces, cada elemento que no sea el último obtiene un margen. Esto es útil si tienes varios elementos en una tarjeta, como este:

… y también :is()y:where()

CSS Selectors Level 4 también es la misma especificación que tiene el :isselector que se puede usar así hoy en día en muchos navegadores:

:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {  color: #BADA55;}/* ... which would be the equivalent of: */section h1, section h2, section h3, section h4, section h5, section h6, article h1, article h2, article h3, article h4, article h5, article h6, aside h1, aside h2, aside h3, aside h4, aside h5, aside h6, nav h1, nav h2, nav h3, nav h4, nav h5, nav h6 {  color: #BADA55;}

Más información

¡Eso es todo! :hasSu uso debería ser bastante útil pronto, y sus primos :isy :notya pueden ser fabulosamente útiles y eso es sólo un pequeño vistazo (solo tres pseudoclases de CSS) que están disponibles en esta nueva especificación.

  • Adrian Bece: conozca a :has, un selector principal de CSS nativo (y más)
  • Bramus Van Damme: el selector CSS :has()es mucho más que un “selector principal”
  • Michelle Barker — :has() ha aterrizado en Safari

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir