SnapDOM vs html-to-image
Two libraries built around the same SVG foreignObject approach — compared on fidelity, fonts, Shadow DOM, plugins and developer experience.
html-to-image and SnapDOM both clone the DOM and render it through SVG foreignObject. SnapDOM adds a plugin pipeline, capture reuse in v3, and options for fonts, exclusions and output sizing.
SnapDOM vs html-to-image, head to head
Both libraries export the same DOM element to PNG five times. Times are averaged, the faster one is highlighted. Run it on your machine — the gap is hardware- and content-dependent.
A quick overview
html-to-image is a fork of dom-to-image with TypeScript support. Its image helpers return data URLs; it also provides Canvas and Blob exports.
SnapDOM exposes capture and export lifecycle hooks. Official plugins add portable HTML, structured context and maps, PDF images, GIF and video alongside filters, timestamps and text transformations. These plugins are separate from the core image and canvas exporters.
Feature matrix
| Feature | SnapDOM | html-to-image |
|---|---|---|
| Active maintenance | Yes | Yes |
Pseudo-elements (::before / ::after) | Supported | Yes |
Web fonts (@font-face) | Embedded; local font option | Embedded |
| Shadow DOM | Open roots | Open roots |
| CSS variables | Yes | Yes |
CSS counter() / counters() | Yes | Depends on the case |
| Line-clamp / multi-line ellipsis | Yes | Depends on the case |
| Plugin system | Yes (official + custom) | No |
| Output formats | SVG · PNG · JPG · WebP · Canvas · Blob | SVG · PNG · JPG · Canvas · Blob |
| PDF export | Plugin | No |
| TypeScript types | Bundled | Bundled |
| License | MIT | MIT |
Support varies by fixture and rendering mode; test your own UI. See the live benchmark for its pixel fixtures and loaded versions.
When to use which
Choose SnapDOM when…
- You use Web Components or Shadow DOM heavily.
- You need CSS counters or line-clamp ellipsis in the captured output.
- You want to add filters, watermarks, ASCII or PDF export without forking the library.
- You need fine-grained font control (
embedFonts,localFonts,excludeFonts).
Check before migrating…
- SnapDOM plugins extend the capture lifecycle; existing html-to-image post-processing needs adapting.
- Compare open Shadow DOM, CSS counters and line-clamp on the components you ship.
- html-to-image has font embedding controls and canvas-based encoding; compare option semantics before mapping them.
Same task, side by side
Capturing #card as a PNG and inserting the resulting image into the page:
html-to-image
import { toPng } from 'html-to-image'; const dataUrl = await toPng(document.querySelector('#card')); const img = new Image(); img.src = dataUrl; document.body.appendChild(img);
SnapDOM
import { snapdom } from '@zumer/snapdom'; const img = await snapdom.toPng(document.querySelector('#card')); document.body.appendChild(img);
Migration snippet
| html-to-image | SnapDOM |
|---|---|
| toPng(el) | (await snapdom.toPng(el)).src |
| toJpeg(el, { quality: 0.9 }) | (await snapdom.toJpg(el, { quality: 0.9 })).src |
| toBlob(el) | snapdom.toBlob(el, { format: 'png' }) |
| toCanvas(el) | snapdom.toCanvas(el) |
| toSvg(el) | snapdom.toRaw(el) |
| { backgroundColor: '#fff' } | { backgroundColor: '#fff' } |
| { pixelRatio: 2 } | { dpr: 2 } |
| { filter: keep } | { exclude: node => !keep(node) } |
| { fontEmbedCSS } | No direct equivalent; embedFonts: 'auto' discovers used fonts |
| — (not supported) | { plugins: [...] } |
// Before import { toPng } from 'html-to-image'; const dataUrl = await toPng(el, { pixelRatio: 2 }); // After import { snapdom } from '@zumer/snapdom'; const img = await snapdom.toPng(el, { dpr: 2 });
Frequently asked questions
What's actually different between html-to-image and SnapDOM?
Both clone the DOM and render via foreignObject. SnapDOM adds capture lifecycle hooks, automatic reuse for eligible repeat captures, and official plugins for HTML, structured context and maps, PDF images, GIF and video. Compare the return types and options in the migration table.
Does SnapDOM render web fonts better than html-to-image?
Both libraries can embed @font-face declarations. SnapDOM v3.x.x defaults to embedFonts: 'auto' for used web fonts and also supports localFonts and excludeFonts. Check the exported text with your actual font files and browser.
Can I add a watermark or filter without forking the library?
Yes — that's exactly what the SnapDOM plugin system is for. Use the colorTint, filter or timestampOverlay plugins, or write your own with two callbacks (afterClone / beforeExport). Browse the plugins page for the full list.
How do I export to PDF?
Use the MIT pdf plugin. Its toPdf() method returns a PDF Blob with selectable text, pagination and links. The plugin is available on npm in @zumer/snapdom-plugins 4.x; see the PDF reference for installation and examples.
Ready to try SnapDOM?
Try the capture and export methods on an element from your project.
Open the demo Installation