🖼️ ChromeのHTML-in-Canvas API、DOMかCanvasかの二択を終わらせにきた

Chrome 148〜150でOrigin Trial中の新API。DOM要素をそのままCanvas/WebGLに描画し、テキスト選択やスクリーンリーダー対応まで維持できる仕組みを解説する。

Figmaやスプレッドシートのブラウザ版を触っていて、「このテキスト入力欄、右クリックのコピペメニューが出ないな」と思ったことはないだろうか。

ああいうアプリの多くはCanvasかWebGLで画面全体を自前描画している。ピクセル単位の制御と描画速度を取りにいった代わりに、ブラウザが標準で持っているテキスト選択・検索・スクリーンリーダー対応を手放している。DOMの親切さと、Canvasの速さ。この二択は長年、Web開発の根本的なトレードオフだった。

Chromeチームが Origin Trial 中の HTML-in-Canvas API は、この二択そのものを崩しにきている。

DOM要素をそのままテクスチャにする

やることはシンプルだ。<canvas> の中に普通の <div><input> を子要素として書き、layoutsubtree 属性を付ける。

<canvas id="canvas" layoutsubtree>
  <div id="form_element">
    <label for="name">Name:</label>
    <input id="name" type="text">
  </div>
</canvas>

このDOMはブラウザの通常のレイアウトエンジンに乗ったまま存在する。テキスト選択もCtrl+Fの検索も、拡張機能によるDOM書き換えも、これまで通り動く。

描画側では、2Dコンテキストなら drawElementImage、WebGLなら texElementImage2D、WebGPUなら copyElementImageToTexture を呼ぶだけで、そのDOM要素の見た目がテクスチャとしてキャンバスに焼き込まれる。

canvas.onpaint = () => {
  ctx.drawElementImage(form_element, 0, 0);
};

見た目はCanvas、実体はDOM。フォームのバリデーションもアクセシビリティツリーも、裏でそのまま生きている。これ、結構おもしろい設計だと思う。

クリック判定はどうなるのか

描画したテクスチャの位置とアクセシビリティ・入力判定用のDOM位置がズレたら意味がない。そこでCSSトランスフォームを使って、描画時の変形量をブラウザ側に伝える仕組みが用意されている。3D空間でCanvasを回転させても、その上のボタンは回転後の見た目通りの位置でクリックを受け付ける。

WebXR空間に浮かぶUIパネルがマウス操作をそのまま受けられる、という説明を読んで、地味に一番驚いた部分だ。

今どこまで動くのか

2026年7月時点でChrome 148〜150のOrigin Trialが進行中。手元で試すだけならChrome Canary 149以降で chrome://flags/#canvas-draw-element を有効化すればいい。Three.jsは THREE.HTMLTexture で実験的に対応済み、PlayCanvasもテクスチャAPI経由で使えるようになっている。

制限もはっきりしているよ。クロスオリジンのDOM要素はセキュリティ上の理由で描画できない。スクロールも自動では追従せず、JavaScript側で位置を更新する必要がある。「魔法のように何でも解決する」タイプの機能ではない。

Zenn・Qiitaはまだ静か

検索してみたが、日本語圏でこのAPIを扱った記事はまだ見当たらない。Canvas APIの基礎解説は大量に出てくるのに、HTML-in-Canvasはゼロだ。Origin Trial段階のAPIなのでプロダクション投入はまだ先だが、Google DocsやFigmaのような「巨大キャンバス+複雑なUI」を作っているチームには効いてくる話だと思う。

自分がCanvasベースのエディタを作るとしたら、フォーム部分だけでもこのAPIに乗せ替えたい。テキスト選択やスクリーンリーダー対応を自前実装で追いかける手間から解放されるなら、その価値は大きい。

Origin Trialが終わってフラグなしで使えるようになったら、あなたのプロダクトのどの部分をDOMに戻したくなるだろうか。

元ネタ: https://developer.chrome.com/blog/html-in-canvas-origin-trial