The browser paints the capture
SnapDOM's second engine hands the captured clone to Chrome's own renderer through the html-in-canvas API. Compare it with the SVG engine and see which plugins run on it.
snapdom(el, { engine: 'html-in-canvas' }) paints the clone SnapDOM already built, styles resolved and images and fonts inlined, with Chrome's own renderer instead of an SVG image. It runs in Chrome 157 and newer, where the API ships without a flag. Anywhere else, or on a capture this engine cannot paint, SnapDOM uses the SVG engine and you get the same result object. The guide explains when to pick it and what SnapDOM adds on top of the raw API.
Try it
Checking this browser…
Quarterly report
Revenue grew 12% this quarter.
Type in the field or change the plan, then capture again. Both columns come from the same clone; only the last step differs.
Plugins
A plugin that works on the clone runs as it is: by the time the browser paints, its change is already in the clone. A plugin with a render hook, beforeRender or afterRender, gets the SVG engine on purpose, because it reads the SVG or does its work at that boundary. Those captures still succeed, through SVG.
| Plugin | Engine | Why | This browser |
|---|---|---|---|
| timestamp-overlay | html-in-canvas | Adds its label to the clone | |
| replace-text | html-in-canvas | Edits text in the clone | |
| filter | html-in-canvas | CSS filter on the clone | |
| color-tint | html-in-canvas | Overlay on the clone | |
| redact-inputs | html-in-canvas | Masks values in the clone. With blocks or attributes it uses SVG: its final pass runs in beforeRender | |
| agent-map | html-in-canvas | Reads the clone, draws on the pixels | |
| context-export | html-in-canvas | Reads the live page | |
| ascii-export | html-in-canvas | Reads the pixels | |
| gif-export | html-in-canvas, every frame | Recaptures with the same options | |
| video-export | html-in-canvas, every frame | Recaptures with the same options | |
| stream | html-in-canvas | Full frames come from the engine | |
| html-export | SVG | Serializes the clone in afterRender | |
| SVG | Its text layer measures the SVG | ||
| vector | SVG | Takes the clone in beforeRender |
How it works
The same clone
Everything up to the render is the normal pipeline: computed styles become classes, pseudo-elements become real nodes, images and fonts become data URLs, and clone plugins run. The engine choice comes after all of that.
A mount the browser can paint
The clone goes into a shadow root under
<canvas content="drawable">, behind the page. Chrome lays it out like any element, with the page's own form controls, scrollbars and text shaping.Two frames, one draw
After one full rendering update the browser holds a snapshot of the mount, and
drawElementImage()paints it at yourscaleanddpr. A blank or unreadable result sends the capture to the SVG engine instead.The bitmap goes straight to the exports
toCanvas(),toPng()and the rest draw from the painted canvas.result.urlis a PNG data URL, made the first time you read it.
Copy-paste example
npm install @zumer/snapdom
import { snapdom } from '@zumer/snapdom'
const result = await snapdom(document.querySelector('#card'), { engine: 'html-in-canvas' })
const png = await result.toPng()
The engine is part of the default build. In a browser without the API the same option gives you the SVG engine, so you can leave it on without a feature check. Nothing else changes: the options, the result object and the plugins are the ones you already use.
What stays on the SVG engine
This engine paints one plain element box. Captures of body or html, a scrolled root, a root or ancestor with a transform or zoom, a root with a filter, and the outerShadows, clip, width and height options all go through SVG, where that geometry is handled. So do captures in browsers without the API.
html-in-canvas is a WICG specification. Chrome 157 ships it without a flag; before that it was an origin trial and chrome://flags/#canvas-draw-element, and Chromium browsers still on those builds want the older layoutsubtree canvas attribute, which is why SnapDOM sets both names. Firefox and Safari have no implementation, so there every capture uses the SVG engine.