Skip to content

HTML-rendering techniques — reference

Diataxis type: reference. Neutral facts for selecting a technique while working. For the reasoning behind these choices see the explanation; for a recipe see the how-to. Current as of 2026-05.

The seven techniques

# Technique Category Renderer Maturity (2026) Accessible / crawlable output Licence
1 Native HTML-in-Canvas (drawElementImage/placeElement) UI → canvas Real browser Chrome 148–151 origin trial; Chromium-only; Gecko/WebKit no signal Yes (only canvas technique that is)
2 DOM→raster libs (html2canvas, html-to-image, snapdom) HTML → image Library's own painter (not the browser) Mixed; html2canvas unmaintained at 1.4.1; snapdom/html-to-image active N/A (flat raster) MIT
3 Satori (+ resvg) / @vercel/og data → image Satori flexbox engine (CSS subset) Stable, active N/A MIT
4 SVG <foreignObject>drawImage HTML → image Real browser (taints canvas) Stable N/A
5 Headless browser (Puppeteer / Playwright) HTML → image/PDF Real Chromium Stable N/A Apache-2.0
6 Canvas-native UI (Konva / Fabric / PixiJS) UI in canvas GPU/2D canvas (no DOM) Stable No (no DOM, no a11y by default) PixiJS/Fabric MIT; Konva GPL-3.0 — verify
7 Perf primitives (OffscreenCanvas, WebGPU) acceleration GPU + workers WebGPU cross-browser since ~Nov 2025

Decision matrix

Goal Use Notes
Dynamic OG / social images Satori / @vercel/og (#3) flexbox-only; no grid/RTL; fonts must be supplied
Export the current view as PNG (client-side) snapdom (#2) fails on backdrop-filter/glass; CORS/tainting applies
Pixel-perfect PDF receipts / contracts Headless Chromium (#5) only path using the complete engine; heavy server dep
Pixel-perfect screenshot of a complex page Playwright / Puppeteer (#5) full CSS (grid, blur, web fonts)
Interactive design-tool / whiteboard canvas Fabric / Konva / PixiJS (#6) not accessible/crawlable by default; check Konva licence
Generative-UI on a public site DOM-first (current approach); HTML-in-Canvas (#1) only as a future prototype canvas-native UI tanks crawlability
Data-viz charts SVG/DOM (Recharts/D3); canvas (#6/#7) only for huge datasets SVG charts are accessible + inspectable

Capability facts

Satori (#3) — the platform's chosen card renderer

  • CSS support is a subset: display: flex and none only — no display: grid, no z-index (paint order = source order), no 3D transforms, no RTL.
  • Every element with more than one child must set display: flex explicitly, or rendering throws.
  • Fonts are not taken from the system; pass fonts: [{ name, data, weight, style }] with TTF/OTF/WOFF buffers (not WOFF2).
  • Images: supply a reachable URL or a base64 data URI; for reliability pre-fetch and inline as a data URI.
  • Output is SVG; rasterise with @resvg/resvg-js (native binding) on Node, or @vercel/og (satori + resvg-WASM, ~500KB bundle cap) on edge.
  • Measured on this project (2026-05): warm render ≈ 320 ms (satori ≈ 18 ms + resvg ≈ 303 ms) for a 1200×630 card; resvg dominates.

DOM→raster libs (#2)

  • html2canvas re-implements CSS painting — it is not a real screenshot; it fails on box-shadow, gradients and backdrop-filter/blur.
  • html2canvas is effectively unmaintained (1.4.1). Active alternatives: html2canvas-pro, html-to-image, snapdom (≈30–100× faster).
  • Cross-origin images without CORS headers taint the canvas; toDataURL then throws a SecurityError. Any <foreignObject>-with-HTML SVG also taints.

Native HTML-in-Canvas (#1)

  • API: layoutsubtree attribute opt-in; drawElementImage() (2D), placeElement() (interactive 2D), texElementImage2D (WebGL), copyElementImageToTexture (WebGPU); redraw on the paint event.
  • Cross-origin content is not drawn (privacy-preserving).
  • Behind chrome://flags/#canvas-draw-element; Chromium-only; not a public-path option in 2026.

Corrections to common assumptions

  • Canvas UI is not accessible or crawlable by default.
  • html2canvas is not a real screenshot and is not actively maintained.
  • Satori is not a full CSS engine — it is flexbox-only.
  • A tainted canvas cannot be exported with toDataURL/toBlob.
  • The native HTML-in-Canvas API is not shippable in 2026 (Chromium OT only).
  • WebGPU is cross-browser as of ~Nov 2025 (no longer experimental).
  • Konva may be GPL-3.0 — verify before commercial/closed-source use; PixiJS, Fabric, two.js, Satori, Puppeteer, Playwright are permissive (MIT/Apache).