Cambios de herencia para el diseño de selección de CSS

Fecha de publicación: 8 de octubre de 2024

A partir de Chrome 131, la herencia de CSS Highlight cambiará para las seudoclases ::selection y ::target-text. Esto es para crear un modelo más intuitivo para la herencia y alinearse con las pseudoclases ::highlight, ::spelling-error y ::grammar-error agregadas recientemente. En esta publicación, se explica el cambio, que no debería causar un impacto visible para la mayoría de los sitios.

Diseño de selección

Aplicar diseño al aspecto del texto seleccionado puede transmitir significado a los usuarios, como el propósito del contenido seleccionado o la imposibilidad de seleccionar el texto. GitHub, por ejemplo, colorea el código seleccionado de manera diferente a la estructura del directorio seleccionado.

CSS admite diseños de selección con el pseudoelemento ::selection, uno de un conjunto de pseudoelementos conocidos como pseudoelementos de resaltado. Estos pseudoelementos controlan cómo aparece el texto en varias acciones del usuario, del navegador o de la secuencia de comandos. Además de la selección, puedes aplicar diseño a los errores ortográficos (::spelling-error), los errores gramaticales (::grammar-error), los objetivos de texto incorporados en URLs (::target-text) y los textos destacados generados por secuencias de comandos (::highlight).

Al igual que con cualquier colección de propiedades CSS, el comportamiento de herencia es una consideración importante cuando se diseña un sitio. En general, los desarrolladores esperan que las propiedades CSS se hereden a través del árbol de elementos del DOM (por ejemplo, font) o que no se hereden en absoluto (por ejemplo, background).

Cambios en el comportamiento de selección en Chrome 131

Considera este fragmento de documento:

p {
  color: red;
}

.blue::selection {
  color: blue;
}
<p class="blue">Some <em>emphasized</em> text that one would expect to be blue</p>

Las declaraciones de estilo del fragmento modifican el color del texto seleccionado, con una regla que coincide con todos los elementos y una que coincide con los que tienen la clase "blue". Cuando se selecciona en Chrome 130 o versiones anteriores, este es el resultado:

El texto que debería ser azul es rojo.

Cuando se selecciona en Chrome 131, el resultado cambia a lo siguiente:

El texto ahora está destacado en azul.

¿Qué cambió? Históricamente, el comportamiento de herencia de las propiedades de selección se implementó a través de la herencia del elemento de origen, en la que la selección usa las propiedades de un ::selection que coincide con el elemento que se selecciona. Las versiones 130 y anteriores de Chrome usan este modelo, en el que el texto destacado no tiene ::selection coincidente porque .blue::selection solo coincide con elementos de la clase "blue", que no tiene el elemento <em>.

Chrome 131 habilita un nuevo comportamiento en el que los elementos heredan el comportamiento de selección de su elemento superior. En el ejemplo anterior, el elemento <em> no tiene ningún ::selection que coincida con él, por lo que hereda los colores de selección del elemento <p>. Esto se conoce como herencia de elementos destacados de CSS y puedes probarlo en versiones anteriores de Chrome habilitando las funciones experimentales de la plataforma web en chrome://flags.

Es probable que los sitios que dependen de propiedades de selección que no heredan vean cambios en la apariencia del texto seleccionado, pero la evidencia de los informes de errores sugiere que hay pocos casos de uso para ese comportamiento.

Las propiedades personalizadas de CSS para la selección siguen funcionando

Muchos sitios simulan la herencia de los elementos destacados de CSS a través del uso de propiedades personalizadas de CSS. Las propiedades personalizadas se heredan a través del árbol de elementos, lo que genera el resultado "heredar de la unidad superior" con un fragmento de código como el siguiente:

:root {
   --selection-color: lightgreen;
}

::selection {
  color: var(--selection-color);
}

.blue {
  --selection-color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text that is blue</p>

Este es el resultado cuando se selecciona en Chrome 130 y 131:

La primera línea es verde y la segunda es azul.

Aquí, cada elemento hereda algún valor de la propiedad --selection-color a través del árbol de elementos, y este color se usa cuando se selecciona el texto. Los elementos con la clase .blue y sus descendientes son azules cuando se seleccionan, y los demás elementos son de color verde claro. Muchos sitios usan esta técnica, y es el método que se recomienda en Stack Overflow.

Para mantener la compatibilidad, el modelo de herencia de CSS Highlight especifica que ::selection (y otros seudoelementos de CSS Highlight) heredan valores de propiedades personalizadas de su elemento de origen (el elemento al que se aplican). Los sitios que usan este método no deberían verse afectados por los cambios en Chrome 131.

Se ignoran las propiedades personalizadas definidas en el pseudoelemento ::selection para evitar comportamientos de herencia en competencia. Debes definir las propiedades en el elemento en sí y, luego, hacer referencia a ellas en el elemento pseudo.

Selectores universales para ::selection inhabilitan la herencia de elementos destacados

Es posible que los sitios que no usan propiedades personalizadas de CSS hayan estado usando un selector universal para establecer el color de texto seleccionado. Como el siguiente CSS, por ejemplo:

::selection /* = *::selection (universal) */ {
  color: lightgreen;
}

.blue::selection {
  color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>

Este es el resultado cuando se selecciona en Chrome 130 (y versiones anteriores) y Chrome 131 (y versiones posteriores):

La primera línea de texto es verde. El segundo es azul, pero la palabra destacada es verde.

La herencia de CSS Highlight no hace que el segundo texto destacado herede el color azul de su elemento superior porque el selector universal coincide con el elemento <em> y aplica el color de resaltado universal, verde claro.

Para obtener los beneficios de la herencia de elementos destacados de CSS, cambia el selector universal para que coincida solo con la raíz, que luego heredarán sus descendientes:

:root::selection {
  color: lightgreen;
}

.blue::selection {
  color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>

El resultado en Chrome 131 se ve de la siguiente manera:

La primera línea de texto es verde. La segunda línea es azul.

Si tu sitio modifica los colores de selección, pero no usa propiedades personalizadas, es probable que tengas un selector universal para el pseudo ::selection. La buena noticia es que tu sitio no se dañará con este cambio en Chrome, pero no podrás disfrutar de los beneficios ergonómicos de la herencia de elementos destacados.

También cambiará el diseño de ::target-text.

Todos los comportamientos y cambios que se describen aquí se aplican al pseudoelemento ::target-text, al igual que a ::selection. Los casos de uso para más de un estilo de texto objetivo en un solo sitio son limitados, y la función es bastante nueva, por lo que es muy poco probable que tu sitio cambie en el comportamiento de ::target-text.

¿Por qué se aplicó este cambio?

Cuando los otros pseudoelementos de destacados estaban en desarrollo, el grupo de trabajo del CSS resolvió implementar la herencia con el modelo de herencia de destacados. Este ya era el método en la especificación del pseudoelemento ::selection, pero los navegadores no lo implementaron. Los pseudoelementos que no son de selección usan la herencia de resaltado, en la que el pseudoelemento se hereda como si fuera una propiedad. Es decir, los elementos heredan los pseudoelementos de resaltado de su elemento superior del documento.

En aras de la coherencia en todos los seudoelementos de destaque, el grupo de trabajo de CSS reiteró la compatibilidad con la herencia de elementos destacados para ::selection, y los navegadores están trabajando para lanzar el nuevo comportamiento, a la vez que intentan no dañar los sitios existentes.

Probar

En el siguiente CodePen, se demuestran los cambios. Pruébala en Chrome 131.