前端圈有一条隐形的墙:DOM 负责结构、文本、无障碍与交互;Canvas / WebGL 负责像素、Shader、粒子与 3D。两边各自很强,却很难融合。
HTML-in-Canvas 是 WICG 正在孵化的提案,试图把这道墙拆掉;
而 Canvas UI 则是基于它(并带降级方案)第一个走红的"GPU 级视觉组件库"。
一、旧世界的三种妥协
想要"网页 UI + 游戏感特效",过去只有三条路,全有硬伤:
- html2canvas / DOM-to-image:截一次图贴到 Canvas。文字不可选、链接不可点、SEO 和无障碍全丢,且 CSS 还原永远不完整。
- iframe + Shader 采样:能保留交互,但跨域与像素读取受限,Shader 采不到内部细节。
- react-three-fiber / Drei
<Html>:把 DOM 贴到 3D 平面上,排版一复杂就崩,坐标对齐是噩梦。
本质矛盾是:Canvas 拿不到"活着的 DOM",DOM 也进不了 GPU 纹理。
二、HTML-in-Canvas:浏览器原生的桥
WICG 提案 HTML-in-Canvas(Chromium 实现名 CanvasDrawElement)给出了一组极小原语:
layoutsubtree属性:标记某个 DOM 子树"允许被画进 canvas"ctx.drawElementImage(el, x, y)(2D)/gl.texElementImage2D(...)(WebGL):把活着的元素按当前样式绘成纹理canvas.onpaint/requestPaint():元素变化或动画帧触发重绘- 返回值是一个 transform,写回
el.style.transform即可让"视觉位置"和"命中测试位置"继续对齐
最小例子(Chrome Canary + chrome://flags/#canvas-draw-element):
const canvas = document.getElementById("c");
const el = document.getElementById("content");
const ctx = canvas.getContext("2d");
canvas.onpaint = () => {
ctx.reset();
const t = ctx.drawElementImage(el, 0, 0);
el.style.transform = t.toString(); // 保持点击/选区对齐
};
canvas.requestPaint();
关键点在于:被画进去的不是截图,是实时 DOM。文字仍可复制、链接仍可点、屏幕阅读器仍能读到、Find-in-page 仍生效。
隐私侧也做了裁剪:跨域 iframe、visited 链接色、待填表单自动填充、系统主题色、拼写检查标记都不会进纹理,降低指纹面。
当前进度(截至 2026-08)
- WICG 孵化中,WHATWG PR 已开,W3C TAG 审查进行中
- Chromium DevTrial 自 M138 起,本地靠 flag,生产可走 Origin Trial 给访客免 flag
- Firefox / Safari:未实现
三、Canvas UI:把提案包成"前端能用的东西"
David Haz(React Bits 作者)做的 Canvas UI(canvasui.dev) 本质是一层封装:
- 底层:优先用 HTML-in-Canvas 把真实 DOM 绘成纹理,再叠 WebGL Shader(流体、玻璃折射、碎裂、VHS、粒子聚散)
- 降级:检测不到
drawElementImage时,自动退化为「普通 HTML + WebGL overlay」,Safari/Firefox 不白屏,只是少一层"DOM 被扭曲"的魔法 - 组件:33 个左右,分四类——流体运动(Liquid/Ripple/Cloth)、火与能量(Blaze/Laser/ForceField)、玻璃光学(Glass/Magnify/Frost/Peel)、复古故障(VHS/Glitch/Asciify/Decrypt);另有 GLB/SVG/图片类 3D 组件不依赖 flag,全浏览器可跑
- 分发:学 shadcn,源码拷贝进项目(
npx shadcn@latest add @canvas-ui/liquid-react),可改、可被 AI 改,带 MCP 让 Claude/Cursor 直接装 - 框架:React / Vue / Svelte / Solid / Preact / Vanilla TS 同一引擎
- 许可:MIT + Commons Clause,商用免费,禁止转卖组件本身
装一个 Liquid 组件大概是这样:
npx shadcn@latest add @canvas-ui/liquid-react
"use client";
import { Liquid } from "@/components/canvas-ui/liquid-react";
export default function Hero() {
return (
<Liquid>
<h1>真实标题,可被选中复制</h1>
<p>鼠标划过时,这段正文被流体扭曲,但链接照样能点。</p>
</Liquid>
);
}
四、它适合在哪用,不适合在哪用
✅ 适合
- 官网 Hero、作品集、活动落地页、创意机构站
- 需要"游戏引擎质感"但又不肯放弃 DOM 无障碍的营销页
- 3D 配置器、可视化看板里的 HUD(坐标轴/图例/筛选器是真实 form)
❌ 不适合
- 后台系统、长文文档、电商下单流——GPU 特效有开销,且实验 API 不该卡业务
- 追求 Baseline 兼容的项目——现在离开 Chromium + flag/OT 就是降级态
- 把整页都套特效:正文可读性会崩
经验法则:把它当"局部镜头"(Glass/Magnify/Ripple/ParticleReveal/Peel),不当"全站渲染器"。
五、为什么这件事值得写进 2026 的前端笔记
- 可访问性不再是特效的牺牲品。过去 Canvas 重特效 = 屏幕阅读器失明;HTML-in-Canvas 让 DOM 即纹理源,a11y 树天然正确。
- 坐标系统一。HUD、图表控件、3D 表面共享一套空间,不再和 overlay z-index 打架。
- 标准还在动,但方向已明。drawElementImage 命名、隐私排除清单、paint 时序都在迭代,现在试水 = 提前影响 API 形状。
- Canvas UI 示范了"实验特性如何产品化":能力检测 + 优雅降级 + 源码分发,比"等标准稳定再动手"更贴近前端现实。
它不会取代 React 或 Vue,也不是下一个 Tailwind。它更像是给 Web UI 开了一道"GPU 后门"——门后面是游戏引擎级别的视觉自由度,门前还是你熟悉的
<a>、<input>和Ctrl+F。
六、上手路径建议
- Chrome Canary →
chrome://flags/#canvas-draw-element开启 → 跑 WICG 官方 demo(立方体上的 HTML、WebGPU jelly slider) - 裸写 20 行
drawElementImage理解 transform 回写机制 - 用 Canvas UI 加一个
Liquid或Glass到自己的 Hero,观察 Safari 下降级表现 - 生产若真要试:去 developer.chrome.com 申 Origin Trial token,别让用户手开 flag
参考链接
- WICG 提案:https://github.com/WICG/html-in-canvas
- Chrome Platform Status:https://chromestatus.com/feature/5172548013916160
- Canvas UI 官网:https://canvasui.dev
- Canvas UI 仓库:https://github.com/DavidHDev/canvas-ui