¡Hola Devs! Esto sí me emociona

¿Ya te tocó querer resaltar el resultado de una búsqueda en la página y la única salida era inyectar <span> o <mark> por todos lados? Pues esa era ya terminó. 🎉

La CSS Custom Highlight API llegó justo para eso. Junto con pseudo-elementos como ::search-text, ::highlight(), ::target-text, ::spelling-error y ::grammar-error, ahora puedes estilizar rangos de texto que nunca fueron envueltos en un elemento — con puro CSS.

Esto cambia el juego para buscadores internos, modos de lectura, editores colaborativos y cualquier cosa que necesite marcar texto sin tocar el DOM. Si alguna vez escribiste un wrapper sobre mark.js solo para colorear un resultado, respira: hay camino mejor. Y si quieres ver cómo la plataforma viene evolucionando en esta dirección, checa esta guía sobre CSS highlight pseudo-elements.

Developer inspecting CSS Custom Highlight API pseudo-elements in browser DevTools Coding Session Visual

Los pseudo-elementos que necesitas conocer

Aquí va el mapa, del más estable al más experimental:

Pseudo-elementoPara qué sirveSoporte
::selectionTexto seleccionado por el usuarioUniversal
::target-textTexto al que apunta un fragmento de URLChrome, Safari
::search-textCoincidencias del "buscar en la página"Chromium
::spelling-error / ::grammar-errorMarcadores nativos de ortografía/gramáticaChromium
::highlight(nombre)Rangos personalizados registrados vía JSChrome 105+, Safari 17.2+

Estilizando el Ctrl+F del navegador

::search-text es el que la banda lleva pidiendo una década. Antes, el resaltado del "buscar en la página" era intocable. Ya no:

/* Resaltado por defecto de las coincidencias */
::search-text {
  background: #ffe066;
  color: #1a1a1a;
}

/* La coincidencia activa (a la que salta el Enter) */
::search-text:current {
  background: #ff7043;
  color: #fff;
  outline: 2px solid #ff7043;
}

Custom Highlight API en la vida real

El truco bueno es registrar tus propios rangos. Sin mutar el DOM, sin <mark> por todos lados, sin reflows pesados en documentos grandes.

// 1. Encuentra el rango que quieres resaltar
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
const ranges = [];
let node;
while ((node = walker.nextNode())) {
  const idx = node.textContent.indexOf('pseudo-elemento');
  if (idx !== -1) {
    const range = new Range();
    range.setStart(node, idx);
    range.setEnd(node, idx + 'pseudo-elemento'.length);
    ranges.push(range);
  }
}

// 2. Regístralos bajo un highlight con nombre
const highlight = new Highlight(...ranges);
CSS.highlights.set('termino-busqueda', highlight);
/* 3. Estiliza el highlight con nombre */
::highlight(termino-busqueda) {
  background-color: #fff3a0;
  text-decoration: underline wavy #e67e22;
}

Listo. Cero elementos wrapper, cero limpieza cuando cambia el término de búsqueda — nomás haces CSS.highlights.clear() y registras de nuevo.

El patrón MicroLighter

Un truco bien chido que anda circulando: armar un syntax highlighter completo sobre la Custom Highlight API. En lugar de emitir <span class="keyword"> por cada token, tokenizas el texto, armas objetos Range y los registras bajo highlights como keyword, string, comment. El CSS se encarga del color. El DOM queda chiquito y cambiar de tema sale casi gratis.

Frontend engineer styling search-text highlight with CSS pseudo-elements on a code editor Programming Illustration

Cuidados, límites y lo que nadie te cuenta

Unos puntos que los demos felices se olvidan de mencionar:

  • Solo aplica un subconjunto de CSS. Los pseudo-elementos de highlight aceptan muy pocas propiedades: color, background-color, text-decoration y sus longhands, text-shadow y algunas más. No puedes setear padding, border, font-size ni display. Si necesitas una caja alrededor del match, esta no es la herramienta.
  • Sin ::before / ::after. No puedes inyectar contenido en un highlight. Es solo estilizado.
  • Los rangos deben estar vivos. Si el DOM cambia, tus rangos pueden quedar inválidos y dejar de renderizar en silencio. Re-registra en mutaciones si el contenido es dinámico.
  • ::search-text es solo Chromium por ahora. Firefox y Safari no lo han liberado. Haz feature-detect con CSS.supports('selector(::search-text)') y ten fallback.
  • Accesibilidad: los highlights son puramente visuales. Los lectores de pantalla no los anuncian. Si el resaltado comunica algo (tipo resultado de búsqueda), replícalo en regiones aria-live o en el nombre accesible.

Receta de progressive enhancement

/* Baseline: funciona en todos lados */
mark.search-hit {
  background: #ffe066;
}

/* Upgrade: sin wrapper en el DOM */
@supports selector(::highlight(termino-busqueda)) {
  ::highlight(termino-busqueda) {
    background: #ffe066;
  }
}

Manda el fallback con <mark>, encima le pones el highlight cuando haya soporte, y borras el fallback cuando Baseline lo alcance. Y si te laten las historias de cómo una primitiva nueva reescribe toda una stack, échale un ojo al caso de escala de WhatsApp con Rust — mismo patrón de "API nueva destraba arquitectura más simple".

¿Y ahora pa' dónde?

  1. Lee la spec de la CSS Custom Highlight API — está corta y se lee bien.
  2. Prueba ::target-text para resaltar deep-links en sitios de documentación.
  3. Ármate una herramientita de anotaciones: toma texto con window.getSelection(), conviértelo a Range, registra el highlight. Aprendes toda la API en una tarde.
  4. Échale ojo a las specs de ::search-text y ::spelling-error — conforme lleguen a más engines, la era del "envuélvelo en un span" se acaba oficialmente.

Web developer reviewing MicroLighter syntax highlighter built with CSS Custom Highlight API Software Concept Art

Cerrando cuentas

Los pseudo-elementos de highlight en CSS son de esas adiciones silenciosas que borran categorías enteras de JavaScript. Si tu codebase todavía inyecta <mark> para resultados de búsqueda, o carga una librería de 40KB solo para colorear tokens, la Custom Highlight API merece una mirada seria este trimestre.

Empieza con ::highlight() para tus propios rangos, encima pon ::search-text y ::target-text donde haya soporte, y mantén un fallback con <mark> para la cola larga. El DOM que no creas es el DOM que no tienes que limpiar. 🚀

Conclusión

Adoptar la Custom Highlight API no es solo una mejora de performance — es un cambio de mentalidad: dejas de tratar el texto como estructura y empiezas a tratarlo como dato. Ese es el tipo de salto que separa al frontend que sobrevive del que se atora. Dale, prueba con un buscador interno esta semana y verás.

Este contenido fue redactado con la asistencia de herramientas de IA, basándose en fuentes confiables, y fue revisado por nuestro equipo editorial antes de su publicación. No reemplaza el asesoramiento de un profesional especializado.