HTML-in-Canvas : Chrome dessine du vrai DOM dans canvas et WebGL
Si vous avez déjà construit une application sur canvas, vous connaissez ce moment : le rendu est rapide, puis quelqu'un demande pourquoi il ne peut pas sélectionner le texte, le chercher avec Ctrl+F ou l'entendre avec un lecteur d'écran. L'API HTML-in-Canvas de Chrome, maintenant en origin trial, répond à cette question. Elle dessine du vrai contenu DOM dans un canvas 2D ou une texture WebGL/WebGPU, et ce contenu reste interactif et accessible.
Le choix qu'elle supprime
Thomas Nattestad et Natalia Markoborodova présentent cela comme un vieux compromis. Le DOM apporte la mise en page du texte, les contrôles de formulaire et toutes les fonctions du navigateur qui s'appuient dessus : outils d'accessibilité, traduction, recherche dans la page, mode lecture, extensions, zoom et remplissage automatique. Canvas, WebGL et WebGPU donnent une grille de pixels et la vitesse du bas niveau, d'où leur usage dans les jeux et des applications comme Google Docs ou Figma. Le prix : le texte dans la grille de pixels perd tout cela, et reconstruire ne serait-ce qu'un texte responsive à la main alourdit le bundle.
Ce que l'on obtient
D'après l'article de Chrome, le contenu dessiné ainsi conserve :
- la mise en page du texte, y compris multiligne et bidirectionnel, avec le CSS appliqué,
- de vrais contrôles de formulaire,
- la sélection, le copier-coller et le menu du clic droit,
- l'arbre d'accessibilité, donc les lecteurs d'écran le lisent comme du HTML normal,
- la recherche dans la page, avec le résultat surligné dans une texture WebGL,
- les extensions et les DevTools : on change une valeur CSS dans l'inspecteur et la texture 3D se met à jour.
La ligne sur le texte bidirectionnel me parle particulièrement. Un texte arabe avec un mot anglais au milieu, c'est typiquement ce que les applications canvas rendent mal, et ici c'est le moteur de texte du navigateur qui s'en charge.
Le fonctionnement, en trois étapes
D'abord, placez le HTML dans le <canvas> et ajoutez l'attribut layoutsubtree, qui demande au navigateur de mettre ce contenu en page et de l'exposer à l'arbre d'accessibilité. Ensuite, dessinez-le dans l'événement paint du canvas, déclenché chaque fois que l'élément doit être redessiné, par exemple pendant une sélection ou une saisie. Enfin, appliquez la transformation renvoyée par l'appel de dessin au style.transform de l'élément, pour que clics et survols tombent là où il est dessiné. Voici l'exemple 2D de l'article :
<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();
};
En WebGL, l'appel est texElementImage2D, qui fonctionne comme texImage2D mais prend un élément DOM. En WebGPU, c'est copyElementImageToTexture sur la file du device. En 3D, le navigateur ne peut pas deviner où votre shader place la texture : vous construisez la matrice et la passez à getElementTransform(). Three.js a déjà un support expérimental avec THREE.HTMLTexture, et PlayCanvas le gère via son API de textures, ce qui évite le calcul des matrices.
Comment l'essayer, et ses limites
L'article indique que l'API est en origin trial de Chrome 148 à 150, à un stade précoce, donc susceptible de changer. Pour tester en local, utilisez Chrome Canary 149 ou plus récent avec le flag chrome://flags/#canvas-draw-element activé. Pour l'activer chez vos visiteurs, inscrivez votre site à l'origin trial.
Les auteurs citent deux limites. Elle ne fonctionne pas avec le contenu d'iframes d'une autre origine, pour des raisons de sécurité et de confidentialité. Et comme le contenu est dessiné en JavaScript, le défilement et les animations dans le canvas ne peuvent pas tourner indépendamment du thread principal comme sur une page normale : réfléchissez avant d'y mettre une longue liste qui défile.
Conseil général : c'est fait pour les applications qui vivent déjà dans un canvas. Une page normale en HTML et CSS a déjà toutes ces fonctions et ne gagne rien à y migrer.
Prochaine étape : installez Chrome Canary, activez le flag et essayez l'exemple 2D ci-dessus avec un de vos champs. Si ça tient, inscrivez-vous à l'essai et gardez une solution de repli pour les autres navigateurs. Source : Chrome for Developers, Introducing the HTML-in-Canvas API origin trial.
Ce que disent les lecteurs