HTML-in-Canvas API

一言まとめ

canvas の子に置いた実 DOM 要素を、DOM として生かしたまま 2D / WebGL / WebGPU に描画する WICG 提案。アクセシビリティツリー・フォーカス・テキスト選択が残るのが html2canvas や SVG foreignObject との決定的な差。2026-06 時点で Chrome の Origin Trial 中、Firefox / Safari は態度未表明。

作成 · 更新 · #canvas#webgl#wicg#accessibility
目次 12 sections
  1. 01 何か
  2. 02 なぜ生まれたか — 従来手法の限界
  3. 03 提案の系譜
  4. 04 API サーフェス(2026-06 時点の WebIDL)
  5. 05 セキュリティ・プライバシーモデル
  6. 06 標準化とブラウザ対応(2026-06-14 時点)
  7. 07 機能検出と graceful degradation
  8. 08 向く用途・向かない用途
  9. 09 エコシステム(2026-06 時点)
  10. 10 現実的な使いどころ(OT 段階)
  11. 11 関連
  12. 12 更新履歴

調査時点: 2026-06。Origin Trial 中の API なので、シグネチャ・ブラウザ対応・標準化状況は変わりうる。実装上の検証(a11y・性能・セットアップ・シェーダー)は HTML-in-Canvas の実現性 に分けた。

何か#

<canvas> の子要素として置いた DOM 要素を、canvas の描画コンテキスト(2D / WebGL / WebGPU)にピクセルとして描く API 群。設計の核は二層構造にある。

  • DOM 層: 子要素は layoutsubtree 属性付き canvas の直接の子として実 DOM に存在し続ける。アクセシビリティツリー、フォーカス、find-in-page、テキスト選択、CSS レイアウト計算、ヒットテストはこの層で動く。子要素自体のペイントは画面に出ない。
  • canvas 描画層: drawElementImage() を呼ぶたびにブラウザが DOM 要素のスナップショットを canvas に転写する。画面に見えるのはこのピクセルだけ。
<canvas layoutsubtree>
├ DOM 層(実在): <input> はフォーカス・入力、<p> は a11y・検索の対象
└ 描画層: ctx.drawElementImage(content, x, y) の戻り値 transform を
content.style.transform に入れて DOM 位置を描画位置に合わせる

子要素に指定した CSS transform は描画には使われず、ヒットテストとアクセシビリティの位置計算にだけ使われる。drawElementImage() が返す DOMMatrix を element.style.transform に代入して両者を同期させるのが基本パターン。

なぜ生まれたか — 従来手法の限界#

canvas の fallback content は実描画と一致する保証がなく、スクリーンリーダー・find-in-page・翻訳が canvas 内のテキストに届かない。これを埋めてきた手法はどれも根本解ではなかった。

手法限界
html2canvasCSS を JS で再実装する近似。box-shadow・clip-path・3D transform・iframe・動画は非対応。外部画像で canvas が tainted になる。サブピクセルのフォント描画を再現できない。公式 FAQ が「完全な CSS 対応は永遠にない」と明言
SVG <foreignObject> + drawImage()Safari で描画失敗や背景画像の欠落が多い。tainting の挙動がブラウザ間で不一致だった(blob URL 経由で Firefox だけ非 tainted。Chrome は 2024 年に Firefox に合わせた)。base64 化した時点で a11y 情報は消える
CSS Houdini Paint APICSS プロパティをトリガーにカスタム描画する仕組みで、既存 DOM 要素のスナップショットを取る API はない
drawWindow()(Firefox 非標準)拡張機能専用。同期 API で Fission と非互換。標準化されなかった
軸html2canvasSVG foreignObjectHoudini PaintHTML-in-Canvas
アクセシビリティなしなしなし実 DOM がツリーに残る
CSS 再現精度部分的ブラウザ依存canvas サブセットレンダリングエンジン直結
入力・フォーカス不可不可不可可
WebGL / WebGPU 統合不可不可不可可
ブラウザ対応(2026-06)全主要全主要(挙動差)ほぼ ChromeChrome のみ(OT)

提案の系譜#

時期できごと
2020-12Microsoft が blink-dev に Intent to Prototype: Canvas Formatted Text。fillText() が 1 行しか描けず、改行・CJK・双方向テキストを JS で再実装する困難が動機
2024-06Google が Intent to Prototype: canvas placeElement()。スコープがテキストから任意の HTML 要素へ拡大
2024-08WICG に canvas-place-element リポジトリ。2024-09 に W3C TAG レビュー #997 と WHATWG issue #10650
2024-09〜2025 初フィードバックを受けて API を immediate-mode に再設計し、WICG/html-in-canvas に移管。TAG #997 は “overtaken” でクローズ
2025-05Chrome M138 で DevTrial(フラグ)。2025-08-21 に WHATWG HTML への PR #11588
2025-09プライバシー設計を更新し、「センシティブ情報を描画できるオプション」を削除
2026-03-13新 TAG レビュー #1204。“Missing: Multi-stakeholder support” ラベル付き
2026-05-19Chrome M148 で Origin Trial 開始(Google I/O で発表)。2026-06-10 に M154 まで延長

著者は Google と Igalia のメンバー 7 名。前身の drawElement / texElement2D という名前は WebGL の gl.drawElements() との混同を避けて drawElementImage / texElementImage2D に改名された。

API サーフェス(2026-06 時点の WebIDL)#

partial interface HTMLCanvasElement {
[CEReactions, Reflect] attribute boolean layoutSubtree;
attribute EventHandler onpaint;
void requestPaint();
ElementImage captureElementImage(Element element);
DOMMatrix getElementTransform((Element or ElementImage) element, DOMMatrix drawTransform);
};
interface mixin CanvasDrawElementImage {
DOMMatrix drawElementImage((Element or ElementImage) element, double dx, double dy);
// dWidth/dHeight 付き、sx/sy/sWidth/sHeight 付きのオーバーロードあり
};
CanvasRenderingContext2D includes CanvasDrawElementImage;
OffscreenCanvasRenderingContext2D includes CanvasDrawElementImage;
partial interface WebGLRenderingContext {
void texElementImage2D(GLenum target, GLenum internalformat,
(Element or ElementImage) element,
optional WebGLCopyElementImageConfig config = {});
};
partial interface GPUQueue {
void copyElementImageToTexture(GPUCopyElementImageSource source,
GPUCopyElementImageDestination destination);
};
[Exposed=(Window,Worker), Transferable]
interface ElementImage { readonly attribute double width; readonly attribute double height; undefined close(); };
interface PaintEvent : Event { readonly attribute FrozenArray<Element> changedElements; };
メンバ役割
layoutsubtree 属性canvas の直接の子要素を CSS レイアウトとヒットテストに参加させる opt-in。子はスタッキングコンテキストと containing block になり、paint containment が効く
paint イベント子要素の描画が変化したフレームに 1 回だけ発火(intersection observer の直後)。changedElements で変化した要素を得る
requestPaint()変化がなくても次フレームで paint を 1 回発火させる。requestAnimationFrame() の類似物
drawElementImage()2D context に描画し、DOM 位置同期用の DOMMatrix を返す。paint の外で呼ぶと前フレームのスナップショットを使う
texElementImage2D() / copyElementImageToTexture()DOM 要素を WebGL / WebGPU のテクスチャへ直接転送
captureElementImage()Transferable な ElementImage を生成。Worker に送って OffscreenCanvas で描ける
getElementTransform()WebGL / WebGPU で drawElementImage() の戻り値に相当する同期用行列を得る
2DWebGLWebGPUOffscreenCanvas(2D)
drawElementImage()○——○(ElementImage 経由)
texElementImage2D()—○——
copyElementImageToTexture()——○—
layoutSubtree / paint / requestPaint() / captureElementImage()canvas 要素側同左同左—

Chrome 150.0.7869.0 で WebGL の texElementImage2D が 5 引数から 3 引数 + config に、WebGPU の copyElementImageToTexture がディクショナリ形式に変わった(Issue #132)。OT 期間中にシグネチャが動く前提で、try { 新 } catch { 旧 } のフォールバックが推奨されている。

セキュリティ・プライバシーモデル#

描画できる情報は白リストで制限される。クロスオリジンコンテンツ(他オリジンの iframe)、訪問済みリンクのスタイル、スペルチェックマーカー、オートフィルのプレビュー、OS のテーマ色・アクセシビリティ色設定は描画から除外される。フォント描画の差がフィンガープリントに使われる懸念と、セキュリティ文書に TODO が残っている点がコミュニティで指摘されている。

標準化とブラウザ対応(2026-06-14 時点)#

ブラウザ状況
ChromeOT が M148〜M154。Intent to Ship 未提出。ローカルは chrome://flags/#canvas-draw-element
BraveChromium 147 以降で同じフラグから有効化できる
Firefoxstandards-positions #1076(2024-09 開設)は verdict 未付与。フィンガープリント懸念を残しつつ stage 2 進行は容認、実装予定なし
Safaristandards-positions #630(2026-03 開設)にコメントなし

WHATWG HTML への統合 PR #11588 は open のまま。TAG レビュー #1204 は進行中で、Google / Igalia 単独推進を TAG が懸念している。open issue は 32 件で、シェーダー歪み時のヒットテスト(#140)、style.transform に流し込む設計(#135)、直接の子要素しか描けない制限(#134)などが残る。将来の retained mode(canvas がコマンドバッファを保持し、スクロールやアニメーションをメインスレッドなしで自動更新)は設計段階で具体的な PR はない。

機能検出と graceful degradation#

const supported =
"layoutSubtree" in HTMLCanvasElement.prototype &&
"drawElementImage" in CanvasRenderingContext2D.prototype;

非対応ブラウザでは layoutsubtree canvas の子要素がそのまま通常の DOM として表示される。「fallback content = 実際の描画内容」という設計なので、degradation は API レベルで保証されている。

向く用途・向かない用途#

類型この API でないと難しい理由公式デモ例
(a) DOM へのシェーダーエフェクトCSS filter は組み込みカーネル限定で任意の GLSL は走らない。スクショ経由だとインタラクティブ性が消えるLiquid Glass Distortion、Elastic Bulge、Pixel Disintegration
(b) 3D 空間へのライブ HTML 埋め込みThree.js の CSS3DRenderer はオーバーレイ方式で、メッシュの裏に回せず他の描画と合成できない3D Room with Live Web Content
(c) ページ遷移・トランジションView Transitions はシェーダー合成ができず、スクショ方式は遷移中に操作できないPage Curl、Morphing Text
(d) スクリーンショット・OG 画像・動画書き出しhtml2canvas の CSS 再現は約 8 割、satori は JSX と制限 CSS への変換が要るHTML-to-Image Export、HTML Video Recording
(e) ゲーム UI・キャンバス系ツールの DOM UIFigma・Google Docs・Miro が独自実装してきたテキストレイアウト・IME・CJK フォールバックをブラウザに委ねられるInteractive Form、Rich Text Canvas Editor
(f) アクセシブルなデータ可視化canvas チャートは非表示の DOM ミラーで a11y を保っており、表示との一致保証が脆いAccessible Charts

CSS / SVG で足りる場合はこの API は過剰。すりガラスは backdrop-filter: blur(8px) saturate(180%)、カスタムカーネルや変位マップは SVG filter(feConvolveMatrix・feDisplacementMap)、レイヤー合成は mix-blend-mode、遷移のモーフィングは View Transitions で済むことが多い。

手法向く用途限界
html2canvas静的な HTML スナップショット高度な CSS 非対応、操作不能
html-to-imagedom-to-image の後継。foreignObject 経由外部フォント・疑似要素・CORS
satoriOG 画像生成既存 HTML をそのまま使えない
Puppeteer / Playwrightピクセルパーフェクトなサーバー側キャプチャヘッドレスブラウザが要る
HTML-in-Canvasブラウザ上でネイティブ描画を書き出すChrome 限定、OT 中

エコシステム(2026-06 時点)#

  • Three.js r184(2026-04-16): THREE.HTMLTexture と InteractionManager が実験的に追加(PR #31233)。InteractionManager が毎フレーム CSS matrix3d を計算し、ブラウザがポインタ・ホバー・フォーカス・入力をネイティブに処理する。
  • PlayCanvas: WebGL バックエンドで対応済み(device.supportsHtmlTextures で検出)。WebGPU は未対応。getElementTransform() で DOM と投影行列を同期する HtmlSync を提供。
  • Babylon.js: フォーラムで議論のみ、公式ロードマップなし。
  • React Three Fiber / drei: 固有の抽象化は見当たらない(Three.js 経由では原理的に可能)。
  • 公式デモサイト(html-in-canvas.dev)が 17 本のリファレンス実装を公開。

現実的な使いどころ(OT 段階)#

  1. プログレッシブエンハンスメントとしての視覚効果(Chrome だけ強化、他は通常 HTML)。
  2. 使用ブラウザを Chrome に固定できる内部ツール・ダッシュボード。
  3. デモ・ポートフォリオ・クリエイティブ作品。
  4. html2canvas をフォールバックに残した段階的移行。

関連#

更新履歴#

  • 2026-06-14: 初版(ローカル調査ノート)
  • 2026-10-17: Wiki へ移植、概念ページとして再構成

出典

  1. https://github.com/WICG/html-in-canvas/blob/main/README.md
  2. https://wicg.github.io/html-in-canvas/
  3. https://developer.chrome.com/blog/html-in-canvas-origin-trial
  4. https://html-in-canvas.dev/demos/
  5. https://groups.google.com/a/chromium.org/g/blink-dev/c/t_nGEmJ_v4s
  6. https://github.com/mozilla/standards-positions/issues/1076
  7. https://github.com/WebKit/standards-positions/issues/630
  8. https://github.com/w3ctag/design-reviews/issues/1204
  9. https://github.com/whatwg/html/pull/11588
  10. https://github.com/WICG/html-in-canvas/issues/132
  11. https://github.com/mrdoob/three.js/pull/31233
  12. https://developer.playcanvas.com/user-manual/graphics/advanced-rendering/html-in-canvas/
  13. https://tympanus.net/codrops/2026/05/13/exploring-the-html-in-canvas-proposal/

同じトピック — Web