html-to-image is a popular, well-maintained fork of dom-to-image with TypeScript support. SnapDOM takes the same idea further with a plugin pipeline, native Shadow DOM walking, and out-of-the-box support for CSS counters, line-clamp and CSS variables.
A quick overview
html-to-image is the most popular community fork of dom-to-image. It modernised the codebase, added TypeScript, and improved fidelity for many edge cases. The API is small and predictable.
SnapDOM is a from-scratch alternative. The capture pipeline is broken into lifecycle hooks (beforeClone, afterClone, beforeRender, afterRender, beforeExport, afterExport), which is what enables its plugin system. Plugins ship for things like CSS filters, color tints, timestamps, ASCII export, PDF export and more.
Feature matrix
| Feature | SnapDOM | html-to-image |
|---|---|---|
| Active maintenance | Yes | Yes |
Pseudo-elements (::before / ::after) | Full | Yes |
Web fonts (@font-face) | Embedded + local | Embedded |
| Shadow DOM | Native | Manual |
| CSS variables | Yes | Yes |
CSS counter() / counters() | Yes | No |
| Line-clamp / multi-line ellipsis | Yes | No |
| Plugin system | Yes (8+ official) | 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 |
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).
html-to-image might still fit when…
- You're already using it and it works for your case — there's no urgent reason to switch.
- You don't need a plugin pipeline and your captures are simple HTML/CSS.
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) | snapdom.toPng(el) |
| toJpeg(el, { quality: 0.9 }) | snapdom.toJpg(el, { quality: 0.9 }) |
| toBlob(el) | snapdom.toBlob(el) |
| toCanvas(el) | snapdom.toCanvas(el) |
| toSvg(el) | (await snapdom(el)).toSvg() |
| { backgroundColor: '#fff' } | { backgroundColor: '#fff' } |
| { pixelRatio: 2 } | { scale: 2 } |
| { filter: node => … } | { filter: node => … } |
| { fontEmbedCSS } | { embedFonts: true } |
| — (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, { scale: 2 });
Frequently asked questions
What's actually different between html-to-image and SnapDOM?
Both clone the DOM and render via foreignObject. SnapDOM adds a plugin system with lifecycle hooks, native Shadow DOM walking, CSS counter resolution, line-clamp support, and ships first-party plugins for filters, color tint, timestamp watermark, ASCII export, PDF export and replace-text.
Does SnapDOM render web fonts better than html-to-image?
Both libraries can embed @font-face declarations into the SVG output. SnapDOM exposes embedFonts as a one-line opt-in and additionally supports localFonts and excludeFonts for fine-grained control over which fonts are embedded.
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 pdfImage plugin. It adds a toPdfImage() method to the result object. See the html-to-png how-to for the same pattern with images.
Ready to try SnapDOM?
Drop it into your project and capture your first element in seconds.
Open the demo Install from npm