HTML in Canvas: The WICG drawElement Proposal

Table of contents

Canvas has always been the web's escape hatch. Need pixel-level control? Canvas. Need to render a chart? Canvas. Need to build a game? Canvas.

But the moment you need styled text, a form input, or anything resembling a real HTML layout inside that canvas, you are on your own. No line wrapping. No bidirectional text support. No accessibility tree. Just fillText() and a prayer.

A new WICG proposal called HTML-in-Canvas is about to change that. It lets you render real, interactive HTML elements directly into a 2D or 3D canvas context. And it is already behind a flag in Chrome Canary.

What HTML-in-Canvas Actually Does

The proposal introduces three new primitives that work together.

First, the layoutsubtree attribute. Add it to a <canvas> element and its children start participating in layout and hit testing. They become containing blocks, get stacking contexts, and receive paint containment. The children are laid out by the browser but not painted to screen until you explicitly draw them.

Second, drawElementImage(). This is the core method. Call it on any direct child of the canvas and it draws that element into the canvas, returning a CSS transform you can apply back to the element to keep its DOM position in sync with its drawn position. This means hit testing, accessibility, and intersection observers all continue to work.

Third, the paint event. It fires whenever any canvas child's rendering changes. Think of it as requestAnimationFrame but scoped to actual visual changes in your HTML subtree. There is also a requestPaint() method for when you need to force an update every frame.

For WebGL and WebGPU, equivalent methods exist: texElementImage2D for WebGL and copyElementImageToTexture for WebGPU. This means you can draw HTML onto 3D surfaces with full texture support.

Why This Matters

The pain points this addresses are real and widespread.

Every charting library has reinvented text rendering. D3, Chart.js, Recharts - they all have custom solutions for axis labels, legends, and tooltips because canvas fillText() is fundamentally inadequate. It cannot handle multi-line text, complex scripts, or right-to-left languages without significant effort. HTML-in-Canvas eliminates that entire problem. You write normal HTML for your labels and draw them into the canvas.

Accessibility is the other big win. Canvas fallback content has always been a lie. The fallback DOM exists for screen readers but there is no guarantee it matches what is actually rendered. With HTML-in-Canvas, the DOM elements are the rendered content. The accessibility tree and the visual output are the same thing.

If you have been building creative tools on the web, this unlocks a category of interactions that previously required iframes, foreignObject hacks, or abandoning canvas entirely.

The Five Use Cases That Just Opened Up

Styled text in canvas. Chart labels that support CSS, line wrapping, and internationalization. No more measuring text widths manually or building custom text layout engines.

Interactive content in canvas. Real form inputs with real cursors, real selection, real autocomplete. The demo on the WICG repo shows a text input inside a canvas that behaves exactly like a normal input because it is a normal input.

HTML on 3D surfaces. Render a full HTML div onto a WebGL or WebGPU texture. The three.js team already has an experimental branch integrating this. You can put a live, interactive HTML element on a rotating 3D cube.

Shader effects on HTML. Apply WebGL shaders to HTML elements. Distortions, transitions, custom blend modes - anything you can do in a fragment shader, you can now do to a DOM element. The jelly slider demo on the WICG repo is a perfect example of this.

Media export. Canvas already supports toBlob() and captureStream(). With HTML-in-Canvas, you can render styled HTML layouts and export them as images or pipe them to a VideoEncoder. This is significant for anyone building content creation tools or automated screenshot pipelines.

How It Works Under the Hood

The timing model is the part that took the most engineering. The paint event fires after the browser's own paint step during update-the-rendering, just after intersection observer callbacks. This means you get a snapshot of how every canvas child would appear in the current frame.

When you call drawElementImage() during the paint event, you draw the current frame's snapshot. When you call it outside the paint event, you get the previous frame's snapshot. This prevents tearing and ensures consistency.

CSS transforms on canvas children are intentionally ignored for drawing but preserved for hit testing and accessibility. This separation is what makes the synchronization model work. You draw the element wherever you want on the canvas, then apply the returned transform to keep the DOM aligned.

For worker threads, captureElementImage() creates a transferable ElementImage snapshot you can send to an OffscreenCanvas in a web worker. This means heavy rendering workloads do not block the main thread.

The Security Model

This is where the proposal gets serious. Drawing HTML into canvas creates obvious fingerprinting and data exfiltration risks. The team has designed a privacy-preserving painting model that explicitly excludes sensitive information from the rendered output.

Cross-origin content in iframes, images, and CSS references is excluded. System colors, themes, and user preferences are excluded. Spelling and grammar markers are excluded. Visited link styling is excluded. Pending form autofill data is excluded. Subpixel text antialiasing is stripped.

This is not an afterthought. The security and privacy questionnaire is detailed and the exclusion list is specific. Whether it is comprehensive enough remains to be seen. Developers have already flagged that the fingerprinting risk documentation has incomplete sections. For anyone working in security-sensitive contexts, this is the part of the spec to watch most closely.

The Accessibility Debate

The proposal claims to improve accessibility and the mechanism is sound. If the DOM element is the source of truth for both rendering and the accessibility tree, they cannot diverge. That is a real improvement over current canvas accessibility patterns.

But the concern from accessibility advocates is broader. If HTML-in-Canvas makes it easy to build canvas-first applications, developers will build canvas-first applications. And canvas-first applications historically lose access to browser-level features: spell checking, dictionary lookups, find-in-page (partially addressed in the spec), and platform-specific accessibility services.

The spec authors are aware of this tension. The proposal explicitly keeps elements in the DOM so that native browser features can interact with them. But the history of canvas and accessibility is not encouraging. Flash died in part because it created a parallel rendering universe that the browser could not inspect. HTML-in-Canvas is designed to avoid that mistake, but the incentive structure - make cool visual effects, ship fast, worry about accessibility later - has not changed.

This matters for anyone building production web applications. The technical capability is there. The discipline to use it responsibly is a different question.

Current Status and How to Try It

The API is behind a flag in Chrome Canary. Enable chrome://flags/#canvas-draw-element and you can start experimenting today. The WICG repo has five working demos: complex rotated text, a pie chart with multi-line labels, a WebGL HTML-on-a-cube, a WebGPU jelly slider effect, and interactive form inputs inside canvas.

The spec authors are actively seeking feedback on what works, what fails, and how the feature interacts with accessibility tools. Issues can be filed on the GitHub repo.

Three.js has an experimental branch integrating HTML-in-Canvas. If you are building 3D web experiences, this is worth watching.

Mozilla's standards position on the proposal is still under discussion. Cross-browser support is not guaranteed yet, but the Chromium implementation is functional and the WICG backing suggests serious intent.

The Bottom Line

HTML-in-Canvas solves a problem that has plagued web developers for over a decade: the wall between structured, accessible HTML and the pixel-level freedom of canvas. The three-primitive design is clean. The security model is thoughtful. The use cases are immediate and practical.

The risk is the same risk that comes with every powerful low-level API. It can be used to build better, more accessible creative tools. It can also be used to build inaccessible, unindexable canvas blobs that ignore everything we learned from the Flash era.

The spec is in incubation. The flag is in Canary. The time to shape this API is now, not after it ships to stable. If you build charts, creative tools, games, or anything that touches canvas, go read the explainer and file your feedback.

The browser just learned a new trick. What you build with it is up to you.

↓ Download carousel