Todos los artículos

HTML-in-Canvas: Chrome dibuja DOM real dentro de canvas y WebGL

Plataforma web · 4 min de lectura ·

Si alguna vez has hecho una aplicación sobre canvas, conoces el momento: los gráficos van rápidos y entonces alguien pregunta por qué no puede seleccionar el texto, buscarlo con Ctrl+F o escucharlo con un lector de pantalla. La API HTML-in-Canvas de Chrome, ya en origin trial, responde a eso. Dibuja contenido DOM real en un canvas 2D o en una textura WebGL/WebGPU, y el contenido sigue siendo interactivo y accesible.

La elección que desaparece

Thomas Nattestad y Natalia Markoborodova lo plantean como un dilema antiguo. El DOM te da maquetación de texto, controles de formulario y todas las funciones del navegador construidas encima: herramientas de accesibilidad, traducción, búsqueda en la página, modo lectura, extensiones, zoom y autocompletado. Canvas, WebGL y WebGPU te dan una cuadrícula de píxeles y velocidad de bajo nivel, por eso los usan los juegos y aplicaciones como Google Docs o Figma. El coste: el texto dentro de la cuadrícula pierde todo eso, y rehacer a mano aunque sea un texto adaptable engorda el bundle.

DOM texto, formularios lectores de pantalla canvas píxeles, 3D velocidad de bajo nivel HTML-in-Canvas el DOM se dibuja en el canvas y sigue siendo DOM
Antes había que elegir un lado. La API dibuja el lado DOM dentro del lado canvas.

Qué obtienes

Según el artículo de Chrome, el contenido dibujado así conserva:

  • la maquetación del texto, incluido texto multilínea y bidireccional, con el CSS aplicado,
  • controles de formulario reales,
  • selección de texto, copiar y pegar, y el menú del clic derecho,
  • el árbol de accesibilidad, así que los lectores de pantalla lo leen como HTML normal,
  • la búsqueda en la página, con la coincidencia resaltada dentro de una textura WebGL,
  • extensiones y DevTools: cambias un valor CSS en el inspector y la textura 3D se actualiza.

La línea del texto bidireccional es la que más me importa. Un texto en árabe con una palabra en inglés en medio es justo lo que las aplicaciones canvas suelen pintar mal, y aquí se encarga el propio motor de texto del navegador.

Cómo funciona, en tres pasos

Primero, pon el HTML dentro del <canvas> y añade el atributo layoutsubtree, que le pide al navegador maquetar ese contenido y exponerlo al árbol de accesibilidad. Segundo, dibújalo en el evento paint del canvas, que salta cada vez que el elemento necesita redibujarse, por ejemplo al seleccionar texto o al escribir. Tercero, aplica la transformación que devuelve la llamada de dibujo al style.transform del elemento, para que los clics y el hover caigan donde está dibujado. Este es el ejemplo 2D del artículo:

<canvas id="canvas" style="width: 200px; height: 200px;" layoutsubtree>
  <div id="form_element">
    <label for="name">Name:</label> <input id="name" type="text">
  </div>
</canvas>
const ctx = document.getElementById('canvas').getContext('2d');
const form_element = document.getElementById('form_element');
const canvas = document.getElementById('canvas');

canvas.onpaint = () => {
  ctx.reset();
  // Draw the form element at x:0, y:0
  let transform = ctx.drawElementImage(form_element, 0, 0);

  // Sync the DOM location with the drawn location
  form_element.style.transform = transform.toString();
};
1. preparar layoutsubtree 2. dibujar evento paint 3. sincronizar style.transform en cada redibujado
Si te saltas el tercer paso, el elemento se dibuja en un sitio y los clics van a otro.

En WebGL la llamada es texElementImage2D, que funciona como texImage2D pero recibe un elemento DOM. En WebGPU es copyElementImageToTexture sobre la cola del dispositivo. En 3D el navegador no puede saber dónde coloca tu shader la textura, así que construyes la matriz tú y se la pasas a getElementTransform(). Three.js ya tiene soporte experimental con THREE.HTMLTexture y PlayCanvas lo admite con su API de texturas, lo que te ahorra el cálculo de matrices.

Cómo probarla, y sus límites

El artículo dice que la API está en origin trial de Chrome 148 a 150 y en una fase temprana, así que los detalles pueden cambiar. Para probarla en local, usa Chrome Canary 149 o posterior con el flag chrome://flags/#canvas-draw-element activado. Para activarla para tus visitantes, registra tu sitio en la origin trial.

Los autores citan dos límites. No funciona con contenido de iframes de otro origen, por seguridad y privacidad. Y como el contenido se dibuja con JavaScript, el scroll y las animaciones dentro del canvas no pueden ir por su cuenta, independientes del hilo principal, como en una página normal, así que piénsalo antes de meter ahí una lista larga con scroll.

Como consejo general: esto es para aplicaciones que ya viven dentro de un canvas. Una página normal hecha con HTML y CSS ya tiene todas estas funciones y no gana nada mudándose a uno.

Si tu aplicación ya dibuja su interfaz en un canvas, HTML-in-Canvas es la primera forma de recuperar texto real, formularios y accesibilidad sin reconstruirlos. Pruébala detrás de una detección de funciones: es una origin trial, no un estándar.

Siguiente paso: instala Chrome Canary, activa el flag y prueba el ejemplo 2D de arriba con uno de tus propios campos. Si funciona, regístrate en la prueba y mantén una alternativa para el resto de navegadores. Fuente: Chrome for Developers, Introducing the HTML-in-Canvas API origin trial.

Notas de los lectores

  1. Todavía no hay notas. La primera siempre es la más valiente.
¿Estás construyendo algo parecido? Puedo ayudarte. Escríbeme por WhatsApp