Tema representativo de entrevista

Entrevista Frontend: ¿Cómo usarías la CSS Custom Highlight API para la búsqueda?

FrontendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Un lector de documentos debe resaltar cientos de coincidencias sin envolver los nodos de texto. ¿Cómo usarías la CSS Custom Highlight API y manejarías rangos desactualizados, selección, rendimiento y compatibilidad?

Planteamiento y contexto

Un lector de documentos muestra coincidencias de búsqueda, anotaciones y el resultado actual en texto enriquecido. Envolver cada coincidencia en un span alteraría la selección, la edición y el diseño. Diseña una solución con la CSS Custom Highlight API que cubra el ciclo de vida de Range, actualizaciones del registro, cascada, estados accesibles, respaldo y rendimiento. Esta es una pregunta frontend sobre renderizado de texto y mejora progresiva.

Qué evalúa el entrevistador

  1. Distinguir entre objetos JavaScript Range, Highlight y ::highlight().
  2. Reconstruir rangos desactualizados tras el reemplazo o edición de texto.
  3. Entender que los resaltados no alteran el DOM y pueden combinarse en cascada con ::selection.
  4. Diseñar contraste, resultado actual, foco y semántica de teclado.
  5. Proporcionar un respaldo seguro y cuantificar el costo.

Preguntas de clarificación a realizar

  • ¿Los navegadores y WebViews de destino soportan la API?
  • ¿El documento es editable, está virtualizado o se vuelve a renderizar con frecuencia?
  • ¿Cuántas coincidencias existen y puede una coincidencia cruzar nodos de texto?
  • ¿Se requieren modo oscuro, colores forzados y lectores de pantalla?
  • ¿Es aceptable un respaldo basado en DOM marcado cuando no hay soporte?

Una respuesta de 30 segundos

“Representaría cada coincidencia como un Range, agruparía los rangos en un Highlight y lo registraría en CSS.highlights para estilizarlo con ::highlight(name). Cuando el texto cambie, eliminaría los registros antiguos y reconstruiría a partir de una versión de texto y desplazamientos (offsets) en lugar de retener nodos desconectados. Separaría las capas de búsqueda, anotaciones y resultado actual; expondría el recuento y el estado de teclado más allá del color. Detectaría el soporte, aplicaría un respaldo seguro de texto marcado y mediría la cantidad de coincidencias, el p95 de actualización, los cuadros por segundo y la memoria.”

Respuesta detallada

Paso 1: Crear rangos y resaltados

La API permite que JavaScript cree objetos Range de texto arbitrarios, los combine en un Highlight y registre ese Highlight en el HighlightRegistry. CSS estiliza los rangos con ::highlight(name) sin agregar elementos envoltorios.

javascript
const range = new Range();
range.setStart(textNode, start);
range.setEnd(textNode, end);
const hit = new Highlight(range);
CSS.highlights.set("search", hit);

El código de producción aún debe manejar rangos entre múltiples nodos y el ciclo de vida de los nodos.

Paso 2: Reconciliar actualizaciones de texto

Persiste una versión del documento, la ruta del nodo de texto y los desplazamientos de caracteres con cada coincidencia. Volver a renderizar o editar puede desconectar un nodo, haciendo que su Range quede obsoleto. Elimina las entradas antiguas del registro y reconstruye a partir del nuevo índice de texto; no conserves únicamente referencias al DOM.

Paso 3: Gestionar capas

Usa nombres separados para la búsqueda, las anotaciones, el resultado actual y las sugerencias de corrección ortográfica. Define la cascada prevista con ::selection y otros resaltados del agente de usuario. Actualizar un único objeto de resultado actual no debería forzar la reconstrucción de todas las coincidencias.

Paso 4: Proporcionar retroalimentación accesible

El color no puede ser la única señal. Expón el recuento del resultado actual, navegación enfocable, un indicador de foco visible y alternativas para colores forzados. No asumas que un lector de pantalla anunciará un resaltado por sí mismo; la lista de resultados debe exponer el estado semántico.

Paso 5: Controlar el rendimiento

Aplica debounce a la entrada, agrupa las actualizaciones del registro por lotes y limita el trabajo a una ventana visible cuando sea posible. Mide el escaneo de texto, el p95 de actualización, el cálculo de estilos, los cuadros de desplazamiento y la memoria. Evita una mutación del registro por cada pulsación de tecla.

Paso 6: Respaldo progresivo

Detecta características y elige Custom Highlight, DOM marcado o una lista de resultados simple. Un respaldo basado en DOM debe escapar el texto, preservar enlaces y evitar envoltorios duplicados anidados. La salida del servidor debe permanecer legible antes de la mejora en el cliente.

Paso 7: Probar y aceptar

Prueba coincidencias entre múltiples nodos, re-renderizado, edición, modo oscuro, colores forzados, copiado, virtualización, RTL y navegadores sin soporte. Compara el texto resultante, el orden del teclado, el primer pintado, los FPS de desplazamiento, el p95 de actualización y la memoria; el respaldo no debe perder coincidencias.

Respuesta modelo

“Mantendría el DOM del documento sin cambios: representaría las coincidencias como Ranges, las agruparía en Highlights, registraría los nombres en CSS.highlights y las estilizaría con ::highlight(). Cada resultado lleva una versión de texto y un desplazamiento; re-renderizar elimina los registros obsoletos y los reconstruye. La búsqueda, las anotaciones y el resultado actual tienen capas separadas, mientras que el recuento, el foco y el estado semántico hacen que el resultado actual sea accesible.

La detección de características selecciona Custom Highlight o un respaldo seguro de DOM marcado/lista de resultados. El debounce, las actualizaciones por lotes y los límites de ventana visible controlan el costo. La aceptación cubre rangos entre nodos, copiado, edición, modo oscuro, colores forzados, virtualización y navegadores no compatibles, comparando p95, FPS, memoria e igualdad de resultados.”

Errores comunes

  • Envolver cada coincidencia en spans → altera la estructura del texto y la selección → preferir Range/Highlight.
  • Retener Ranges antiguos → los re-renderizados desconectan nodos → reconstruir por versión de texto.
  • Usar solo color → usuarios con colores forzados y daltonismo pierden el estado → agregar estado semántico y foco.
  • Mutar en cada tecla → provoca churn de estilos → aplicar debounce y procesar por lotes.
  • Concatenar HTML de respaldo → genera riesgo de inyección y anidamiento → escapar y delimitar el rango marcado.

Preguntas de seguimiento y respuestas

Pregunta de seguimiento 1: ¿Por qué no usar spans?

Custom Highlight deja el DOM intacto, reduciendo la interferencia con la selección, la edición y el diseño. Los spans siguen siendo un respaldo de compatibilidad con controles de escape y anidamiento.

Pregunta de seguimiento 2: ¿Qué le sucede a un Range después de editar?

Su nodo puede ser reemplazado o desconectado. Reconstruye a partir de la nueva versión de texto y los desplazamientos en lugar de usar la referencia antigua.

Pregunta de seguimiento 3: ¿Los lectores de pantalla anunciarán el resaltado?

No asumas que lo harán. Expón el recuento de resultados, el estado actual y la navegación por teclado como texto semántico.

Pregunta de seguimiento 4: ¿Cómo demuestras que no hay regresiones?

Usa documentos y recuentos de coincidencias fijos para comparar el p95 de actualización, el trabajo de estilo, los FPS de desplazamiento, la memoria, el comportamiento de copiado y la virtualización.

Fuentes públicas

Preguntas relacionadas