Logotipo de Zephyrnet

API de resaltado personalizado de CSS: el futuro de resaltar rangos de texto en la Web

Fecha:

Estilizar rangos de texto en el software es algo muy útil para poder hacer. Afortunadamente, tenemos la API CSS Custom Highlight que esperamos porque representa el futuro de los rangos de texto de estilo en la web.

Captura de pantalla de animación de la demostración de la API CSS Custom Highlight.

Un ejemplo: si alguna vez ha utilizado software de edición de texto como Google Docs, Word o Dropbox Paper, verá que detectan errores ortográficos y gramaticales y muestran pequeños y agradables subrayados ondulados debajo de ellos para llamar la atención. Los editores de código como VS Code hacen lo mismo con los errores de código.

Otro caso de uso muy común para resaltar texto es buscar y resaltar, donde se le proporciona un cuadro de entrada de texto y al escribirlo busca resultados coincidentes en la página y los resalta. Intenta presionar Ctrl/+ F en su navegador web ahora mismo y escriba algún texto de este artículo.

El navegador mismo a menudo maneja estas situaciones de estilo. Áreas editables (como un <textarea>) obtener garabatos ortográficos automáticamente. El comando de búsqueda resalta el texto encontrado automáticamente.

Pero, ¿y cuando queremos hacer este tipo de estilismo nosotras mismas? Hacer esto en la web ha sido un problema común durante mucho tiempo. Probablemente ha costado a muchas personas mucho más tiempo del que debería.

Este no es un problema simple de resolver. No estamos simplemente envolviendo texto en un <span> con una clase y aplicando algo de CSS. De hecho, esto requiere ser capaz de resaltar correctamente múltiples rangos de texto a través de un árbol DOM arbitrariamente complejo, y posiblemente cruzando los límites de los elementos DOM.

Hay dos soluciones comunes para esto, que incluyen:

  1. estilo de pseudo-elementos de rango de texto, y
  2. creando su propio sistema de resaltado de texto.

Los revisaremos primero y luego echaremos un vistazo a la próxima API CSS Custom Highlight que puede cambiarlo todo. pero si eres

Solución potencial n.º 1: rangos de texto con capacidad de estilo

Probablemente el rango de texto con capacidad de estilo más conocido es la selección del usuario. Cuando utiliza su dispositivo señalador para seleccionar un fragmento de texto en una página web, un Selection el objeto se crea automáticamente. De hecho, intente seleccionar texto en esta página ahora mismo y luego ejecute document.getSelection() en la consola de DevTools. Debería ver información de ubicación sobre el texto seleccionado.

Ventana de DevTools que muestra la posición de la selección actual en la consola.

Resulta que también puede crear una selección de texto mediante programación desde JavaScript. Aquí hay un ejemplo:

// First, create a Range object.
const range = new Range(); // And set its start and end positions.
range.setStart(parentNode, startOffset);
range.setEnd(parentNode, endOffset); // Then, set the current selection to this range.
document.getSelection().removeAllRanges();
document.getSelection().addRange(range);

La última pieza del rompecabezas es diseñar esta gama. CSS tiene un pseudo-elemento llamado ::selection para hacer precisamente eso, y es compatible con todos los navegadores.

::selection { background-color: #f06; color: white;
}

Aquí hay un ejemplo que usa esta técnica para resaltar todas las palabras en una página una tras otra:

En la parte superior de la ::selection pseudo-elemento, hay una serie de otros pseudo-elementos:

  • ::target-text selecciona el texto al que se ha desplazado en navegadores compatibles con desplazamiento a texto característica. (DND)
  • ::spelling-error selecciona el texto que el navegador marca como que contiene un error ortográfico. (DND)
  • ::grammar-error selecciona el texto que el navegador marca como que contiene un error gramatical. (DND)

Desafortunadamente, la compatibilidad con el navegador no es excelente aquí y, aunque estos rangos son útiles por derecho propio, no se pueden usar para diseñar piezas de texto personalizadas, solo las predefinidas por el navegador.

Por lo tanto, la selección de texto del usuario es buena porque es relativamente simple de implementar y no cambia el DOM de la página. Por supuesto, Range los objetos son esencialmente coordenadas de segmentos en la página, en lugar de elementos HTML que deben crearse para existir.

Sin embargo, un inconveniente importante es que al crear una selección se restablece lo que el usuario ya haya seleccionado manualmente. Intente seleccionar texto en la demostración anterior para probar esto. Verá cómo desaparece tan pronto como el código mueva la selección a otro lugar.

Solución potencial #2: Sistema de resaltado personalizado

Esta segunda solución es prácticamente lo único que puede hacer si usa el Selection el objeto es insuficiente para ti. Esta solución gira en torno a hacer todo usted mismo, utilizando JavaScript para insertar nuevos elementos HTML en el DOM donde desea que aparezca el resaltado.

Desafortunadamente, esto significa mucho más JavaScript para escribir y mantener, sin mencionar que obliga al navegador a recrear el diseño de la página cada vez que cambia el resaltado. Además, hay casos extremos complicados, por ejemplo, cuando desea resaltar un fragmento de texto que abarca varios elementos DOM.

Ilustración que muestra una línea de HTML con un elemento de énfasis y un elemento fuerte con un resaltado amarillo brillante que los atraviesa.

Curiosamente, CodeMirror y Mónaco (la biblioteca del editor de texto de JavaScript que impulsa VS Code) tiene su propia lógica de resaltado. Usan un enfoque ligeramente diferente donde los aspectos más destacados están contenidos en una parte separada del árbol DOM. Las líneas de texto y los segmentos resaltados se representan en dos lugares diferentes en el DOM que luego se colocan uno sobre el otro. Si inspecciona el subárbol DOM que contiene el texto, no hay resaltados. De esta manera, los resaltados se pueden volver a renderizar sin impactar las líneas de texto y tener que introducir nuevos elementos dentro de ellas.

En general, parece que falta una función de resaltado impulsada por el navegador. Algo que ayudaría a resolver todos estos inconvenientes (sin interferencia con la selección de texto del usuario, soporte de selección múltiple, código simple) y sería más rápido que las soluciones hechas a medida.

Afortunadamente, ¡eso es de lo que estamos aquí para hablar!

Ingrese la API de resaltado personalizado de CSS

La API de resaltado personalizado de CSS es una nueva especificación W3C (actualmente en estado de Borrador de trabajo) que hace posible diseñar rangos de texto arbitrarios desde JavaScript. El enfoque aquí es muy similar a la técnica de selección de texto del usuario que revisamos anteriormente. Brinda a los desarrolladores una forma de crear rangos arbitrarios, desde JavaScript, y luego diseñarlos usando CSS.

Creación de rangos de texto

El primer paso es crear los rangos de texto que desea resaltar. que se puede hacer usando un Range en JavaScript. Entonces, como hicimos al configurar la selección actual:

const range = new Range();
range.setStart(parentNode, startOffset);
range.setEnd(parentNode, endOffset);

Vale la pena señalar que el setStart y setEnd Los métodos funcionan de manera diferente si el nodo pasado como primer argumento es un nodo de texto o no. Para los nodos de texto, el desplazamiento corresponde al número de caracteres dentro del nodo. Para otros nodos, el desplazamiento corresponde al número de nodos secundarios dentro del nodo principal.

También vale la pena señalar que setStart y setEnd no son las únicas formas de describir dónde comienza y termina un rango. Echa un vistazo a la otros métodos disponible en el Range clase para ver otras opciones.

Crear destacados

El segundo paso consiste en crear Highlight objetos para los rangos creados en ese último paso. A Highlight objeto puede recibir uno o más Ranges. Entonces, si desea resaltar un montón de piezas de texto exactamente de la misma manera, probablemente debería crear una sola Highlight objeto e inicializarlo con todos los Ranges que corresponden a estos fragmentos de texto.

const highlight = new Highlight(range1, range2, ..., rangeN);

Pero también puedes crear tantos Highlight objetos que necesites. Por ejemplo, si está creando un editor de texto colaborativo en el que cada usuario obtiene un color de texto diferente, puede crear uno Highlight objeto por usuario. A cada objeto se le puede aplicar un estilo diferente, como veremos a continuación.

Registro de momentos destacados

Ahora resaltar objetos por sí solos no hace nada. Primero deben registrarse en lo que se llama el registro destacado. Esto se hace usando el API de aspectos destacados de CSS. El registro funciona como un mapa donde puede registrar nuevos aspectos destacados dándoles nombres, así como eliminar elementos destacados (o incluso borrar todo el registro).

A continuación se explica cómo registrar un único punto culminante.

CSS.highlights.set('my-custom-highlight', highlight);

Cuando la my-custom-highlight es el nombre de su elección y highlight es un Highlight objeto creado en el último paso.

Aspectos destacados del estilo

El paso final es aplicar estilo a los reflejos registrados. Esto se hace con el nuevo CSS. ::highlight() pseudo-elemento, utilizando el nombre que eligió al registrar el Highlight objeto (que es my-custom-highlight en nuestro ejemplo anterior).

::highlight(my-custom-highlight) { background-color: yellow; color: black;
}

Vale la pena señalar que, al igual que ::selection, un subconjunto de propiedades CSS solo se puede usar con el ::highlight() pseudo-elemento:

Actualización de destacados

Hay varias formas de actualizar el texto resaltado en la página.

Por ejemplo, puede borrar el registro destacado junto con CSS.highlights.clear() y luego empezar de nuevo desde el principio. O bien, también puede actualizar los rangos subyacentes sin tener que volver a crear ninguno de los objetos. Para esto, utilice el range.setStart y range.setEnd métodos de nuevo (o cualquiera de los otros Range métodos) y los resaltados serán repintados por el navegador.

Pero el Highlight el objeto funciona como un JavaScript Set, por lo que esto significa que también agrega nuevos Range se opone a un existente Highlight highlight.add(newRange) o quitar un Range highlight.delete(existingRange).

En tercer lugar, también puede agregar o eliminar Highlight objetos de la CSS.highlights registro. Dado que esta API funciona como un JavaScript Map, puede set y delete para actualizar el registrado actualmente Highlights.

Soporte del navegador

La especificación para la API CSS Custom Highlight es relativamente nueva y su implementación en los navegadores aún está incompleta. Entonces, aunque será una adición muy útil a la plataforma web, aún no está lista para su uso en producción.

El equipo de Microsoft Edge está implementando la API CSS Custom Highlight en Chromium en este momento. De hecho, la función ya se puede usar en las versiones Canary en este momento al habilitar el indicador de funciones de la plataforma web experimental (en about:flags). Actualmente no hay un plan firme sobre cuándo se enviará la función en Chrome, Edge y otros navegadores basados ​​en Chromium, pero se está acercando mucho.

La API también es compatible con Safari 99 + pero detrás de un indicador de experimento (Desarrollo → Funciones experimentales → Resaltar API), y la interfaz es un poco diferente en el sentido de que usa StaticRange objetos en su lugar.

Firefox aún no es compatible con la API, aunque puedes lee la posición de Mozilla al respecto para obtener más información.

De demostración

Hablando de Microsoft Edge, tienen una demostración configurada en la que puede tomar la API CSS Custom Highlight para una prueba de manejo. Pero antes de probar la demostración, asegúrese de estar usando Chrome o Edge Canary con el indicador de características de la plataforma web experimental en el about:flags .

/botón Ver la demo

La demostración utiliza la API de resaltado personalizado para resaltar rangos de texto en la página según lo que escriba en el campo de búsqueda en la parte superior de la página.

Después de que se carga la página, el código JavaScript recupera todos los nodos de texto en la página (usando un Caminante de árboles) y cuando el usuario escribe en el campo de búsqueda, el código itera sobre estos nodos hasta que encuentra coincidencias. Esas coincidencias luego se usan para crear Range objetos, que luego se resaltan con la API de resaltado personalizado.

Pensamientos Finales

Entonces, ¿realmente vale la pena esta nueva API de resaltado proporcionada por el navegador? ¡Totalmente!

Por un lado, incluso si la API CSS Custom Highlight puede parecer un poco complicada al principio (es decir, tener que crear rangos, luego resaltar, luego registrarlos y finalmente diseñarlos), sigue siendo mucho más simple que tener que crear nuevos elementos DOM e insertar ellos en los lugares correctos.

Más importante aún, los motores de navegación pueden diseñar estos rangos muy, muy rápido.

La razón por la que solo se permite usar un subconjunto de propiedades CSS con el ::highlight() pseudo-elemento es que el subconjunto solo contiene propiedades que el navegador puede aplicar de manera muy efectiva sin tener que recrear el diseño de la página. Resaltar rangos de texto mediante la inserción de nuevos elementos DOM en la página que los rodea requiere que el motor trabaje mucho más.

Pero no confíes en mi palabra. fernando fiori, que trabajó en la API, creó este bonito demostración de comparación de rendimiento. En mi computadora, la API de resaltado personalizado de CSS funciona en promedio 5✕ más rápido que el resaltado basado en DOM.

Con el soporte experimental de Chromium y Safari ya aquí, nos estamos acercando a algo que se puede usar en producción. ¡No puedo esperar a que los navegadores admitan la API de Resaltado personalizado de manera constante y ver qué características desbloqueará!


API de resaltado personalizado de CSS: el futuro de resaltar rangos de texto en la Web publicado originalmente el Trucos CSS. Debieras obtener el boletín.

punto_img

Información más reciente

punto_img