Tous les articles

HTML-in-Canvas : Chrome dessine du vrai DOM dans canvas et WebGL

Plateforme web · 4 min de lecture ·

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.

DOM texte, formulaires lecteurs d'écran, recherche canvas pixels, 3D vitesse bas niveau HTML-in-Canvas le DOM est dessiné dans le canvas et reste du DOM
Avant, il fallait choisir un camp. L'API dessine le côté DOM dans le côté canvas.

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();
};
1. préparer layoutsubtree 2. dessiner événement paint 3. synchroniser style.transform à chaque nouveau dessin
Sans la troisième étape, l'élément est dessiné à un endroit et les clics partent ailleurs.

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.

Si votre application dessine déjà son interface dans un canvas, HTML-in-Canvas est le premier moyen de retrouver vrai texte, formulaires et accessibilité sans tout reconstruire. Testez-la derrière une détection de fonctionnalité : c'est un origin trial, pas un standard.

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

  1. Pas encore de mot. Le premier est toujours le plus courageux.
Vous construisez quelque chose du genre ? Je peux vous aider. Écrivez-moi sur WhatsApp