en CSS

Selectores CSS avanzados 4/4 – :is() y :where()

:where() e :is() son dos selectores con idéntica función, que deberían ser ya parte de cualquier nuevo desarrollo que use CSS por las razones que veremos a continuación, se podría decir que marcan un antes y un después en la forma de escribir nuestros selectores. Por ello, quiero cerrar con ellos esta serie de artículos que empezó con selectores avanzados nth-child.

Función de los selectores :is() y :where()

Las pseudo-clases CSS :is() y :where() son funciones a las que se les puede pasar una lista de argumentos , seleccionando todo elemento seleccionable por cualquiera de los selectores contenidos en dicha lista.

De esta forma, si queremos aplicar una regla a un elemento en el caso de ser hijo de varios tipos de elementos diferentes, podremos hacerlo así:

:is (header, aside, footer) li {
  list-style: none;
}

Importante: los pseudo-elementos no están permitidos dentro de la lista de selectores de estas funciones CSS, lo que no excluye pseudo-clases como :hover, :focus o :valid.

Diferencias entre :is() y :where()

La diferencia principal entre estos dos selectores es que con :where() la especificidad es cero, mientras que con :is() la especificidad será la que corresponda al selector de la lista con mayor especificidad.

/*Los selectores resultantes de la siguiente función :where() tendrán todos una especificidad de cero (0,0,0)*/
:where (header, .header) li {
 list-style: none;
}
/*Los selectores resultantes de la siguiente función :is() tendrán una especificidad de once (0,1,1)*/
:is (header, .header) li {
 list-style: none;
}

Otra diferencia notable entre ellos es la retro-compatibilidad con versiones anteriores de navegadores. En este caso, :is() se lleva el punto ganador, aunque el mérito no es totalmente suyo sino de sus predecesores :matches() y :any().

:matches() y :any()

La pseudo-clase :matches() es el nombre que se le dio a :is() en un borrador anterior y algunos navegadores podrían implementarlo como alias ‘legacy’ para este selector. Aunque actualmente sólo versiones anteriores de Safari lo soportan junto con la versión prefijada :-webkit-any() que usan también el resto de navegadores webkit en sus versiones más antiguas, pero también algunos en sus versiones actuales. Firefox por su lado usa :-moz-any(). Por ello podemos obviar :matches() en favor de las versiones prefijadas de :any() si queremos dar retro-compatibilidad a nuestro código:

:-webkit-any(header, aside, footer) li {
  list-style: none;
}
:-moz-any(header, aside, footer) li {
  list-style: none;
}
:is(header, aside, footer) li {
  list-style: none;
}

Que :is() tenga variantes prefijadas que dan compatibilidad a versiones más antiguas de navegadores webkit de las que da :where(), no quiere decir que no podamos usar este último. Si tus usuarios no usan versiones de Chrome anteriores a la 88, será totalmente seguro.

Ventajas del uso de :is() y :where()

Reducción del peso y de la especificidad

Gracias a la simplificación el código de las agrupaciones o listas de selectores y, además en el caso de :where(), de la reducción las anidaciones como consecuencia de declarar selectores base con especificidad cero, se obtiene mayor limpieza en nuestras hojas de estilo y consecuentemente un menor peso.

/*La especificidad del siguiente selector es (0,0,1)*/
:where(.header, .sidebar, .footer) :is(li,dt,dd) { list-style: none; }

/*Por ello podríamos sobrescribirlo con este otro código de especificidad (0,0,2)*/
aside li{ list-style: initial; }

/*Mientras que las de sus equivalentes mucho más largos es (0,2,1) cada uno*/
.header li, .header dt, .header dd,
.sidebar li, .sidebar dt, .sidebar dd,
.footer li, .footer dt, .footer dd { list-style: none; }

Podréis haceros una idea del código que sería necesario para sobrescribir todos estos selectores. De hecho, si trabajáis con frameworks CSS, seguro que estaréis familiarizados con grandes grupos de anidaciones interminables.

Forgiving selector list

Os habréis percatado de que el código usado para dar compatibilidad a navegadores antiguos no lo hemos agrupado. Esto es porque las listas de selectores en CSS tienen un pequeño problema: si uno de los selectores de la lista no es soportado por el navegador, la lista completa queda invalidada.

:is() y :where() solucionan este problema, siempre y cuando nuestros selectores no sean pseudo-elementos, pues nos permiten agrupaciones de selectores independientemente de su soporte en los navegadores. Esto es posible gracias al uso de lo que se llaman <forgiving-selector-lists>, que analizan cada uno de los selectores de la lista individualmente, eliminando aquellos que no son válidos y devuelven una nueva lista con los selectores restantes.

De esta forma, a la vez que solventamos un problema de compatibilidad de los selectores, de nuevo, obtenemos una reducción de nuestro código gracias a que podemos agruparlos sin preocuparnos del soporte que puedan darle los navegadores.

¿Os ha gustado el artículo? Pues dadle al like… NO, es broma ;), pero podéis suscribiros desde la home o dejar un comentario o pregunta si tenéis cualquier duda.

Hasta el próximo.

Escribe un comentario

Comentario