HTML-in-Canvas: Chrome zeichnet echtes DOM in Canvas und WebGL
Wenn du schon mal eine Canvas-App gebaut hast, kennst du den Moment: Die Grafik ist schnell, und dann fragt jemand, warum man den Text nicht markieren, nicht mit Strg+F durchsuchen und nicht mit dem Screenreader hören kann. Die HTML-in-Canvas-API von Chrome, jetzt im Origin Trial, ist eine Antwort darauf. Sie zeichnet echten DOM-Inhalt in ein 2D-Canvas oder eine WebGL/WebGPU-Textur, und der Inhalt bleibt interaktiv und barrierefrei.
Die Entscheidung, die wegfällt
Thomas Nattestad und Natalia Markoborodova beschreiben es als alten Zielkonflikt. Das DOM bringt Textlayout, Formularelemente und alle Browserfunktionen, die darauf aufbauen: Barrierefreiheit, Übersetzung, Suche auf der Seite, Lesemodus, Erweiterungen, Zoom und Autofill. Canvas, WebGL und WebGPU liefern ein Pixelraster und Low-Level-Tempo, deshalb setzen Spiele und Apps wie Google Docs oder Figma darauf. Der Preis: Text im Pixelraster verliert all diese Funktionen, und schon responsiven Text selbst nachzubauen macht das Bundle größer.
Was du bekommst
Laut dem Chrome-Beitrag behält so gezeichneter Inhalt:
- Textlayout, auch mehrzeilig und bidirektional, mit angewendetem CSS,
- echte Formularelemente,
- Textauswahl, Kopieren und Einfügen sowie das Kontextmenü,
- den Accessibility-Tree, Screenreader lesen ihn also wie normales HTML,
- die Suche auf der Seite, mit dem Treffer direkt in einer WebGL-Textur markiert,
- Erweiterungen und DevTools: Du änderst einen CSS-Wert im Inspector und die 3D-Textur aktualisiert sich.
Die Zeile zu bidirektionalem Text ist für mich die wichtigste. Arabischer Text mit einem englischen Wort darin ist genau das, was Canvas-Apps meistens falsch darstellen, und hier übernimmt die Text-Engine des Browsers selbst.
So funktioniert es, in drei Schritten
Erstens: Leg das HTML in das <canvas> und füg das Attribut layoutsubtree hinzu. Damit layoutet der Browser den Inhalt und gibt ihn an den Accessibility-Tree weiter. Zweitens: Zeichne ihn im paint-Event des Canvas, das immer dann feuert, wenn das Element neu gezeichnet werden muss, etwa beim Markieren oder Tippen. Drittens: Setz die Transformation, die der Zeichenaufruf zurückgibt, auf style.transform des Elements, damit Klicks und Hover dort ankommen, wo es gezeichnet ist. Das ist das 2D-Beispiel aus dem Beitrag:
<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();
};
Bei WebGL heißt der Aufruf texElementImage2D. Er funktioniert wie texImage2D, nimmt aber ein DOM-Element. Bei WebGPU ist es copyElementImageToTexture auf der Device-Queue. In 3D kann der Browser nicht wissen, wo dein Shader die Textur hinlegt, also baust du die Matrix selbst und gibst sie an getElementTransform(). Three.js hat schon experimentellen Support über THREE.HTMLTexture, PlayCanvas über seine Textur-API, und das nimmt dir die Matrizenrechnung ab.
Wie du es testest, und die Grenzen
Laut Beitrag ist die API von Chrome 148 bis 150 im Origin Trial und in einem frühen Stadium, Details können sich also ändern. Lokal testest du mit Chrome Canary 149 oder neuer und aktiviertem Flag chrome://flags/#canvas-draw-element. Für deine Besucher meldest du deine Seite für den Origin Trial an.
Die Autoren nennen zwei Grenzen. Inhalte aus iframes anderer Origins funktionieren nicht, aus Sicherheits- und Datenschutzgründen. Und weil der Inhalt per JavaScript gezeichnet wird, können Scrollen und Animationen im Canvas nicht unabhängig vom Main Thread laufen wie auf einer normalen Seite. Überleg dir also gut, ob eine lange scrollende Liste da hineingehört.
Als allgemeiner Rat: Das ist für Apps gedacht, die ohnehin in einem Canvas leben. Eine normale Seite aus HTML und CSS hat all diese Funktionen schon und gewinnt durch einen Umzug nichts.
Nächster Schritt: Installier Chrome Canary, schalte das Flag ein und probier das 2D-Beispiel oben mit einem deiner eigenen Formularfelder. Wenn es hält, melde dich für den Trial an und behalte einen Fallback für alle anderen Browser. Quelle: Chrome for Developers, Introducing the HTML-in-Canvas API origin trial.
Notizen der Leser