SnapDOM vs dom-to-image
Compare the original dom-to-image API with SnapDOM: rendering approach, plugin exports and the return types to change during migration.
dom-to-image uses SVG foreignObject to capture the DOM. SnapDOM uses that rendering approach with support for open Shadow DOM, CSS counters and a plugin lifecycle.
SnapDOM vs dom-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
dom-to-image clones a node, inlines CSS and assets, and wraps it in a <foreignObject> for the browser to render. Its API returns image data URLs or a PNG Blob. Check its repository for current releases and supported browsers.
SnapDOM is a from-scratch implementation of the same idea, with active development and a plugin system on top. The capture pipeline is exposed through lifecycle hooks (beforeClone, afterClone, beforeRender, afterRender, beforeExport, afterExport) so you can alter capture state, observe exports, and add custom exporters without forking the library.
Feature matrix
| Feature | SnapDOM | dom-to-image |
|---|---|---|
| Release history | See repository | See repository |
Pseudo-elements (::before / ::after) | Supported | Passes tested fixture |
Web fonts (@font-face) | Embedded | Embedded |
| Shadow DOM | Open roots | No |
| CSS variables | Yes | Partial |
CSS counter() / counters() | Yes | Depends on the case |
| Line-clamp / multi-line ellipsis | Yes | Depends on the case |
| Plugin system | Yes | No |
| Output formats | SVG · PNG · JPG · WebP · Canvas · Blob | SVG · PNG · JPG · Blob |
| ES Module build | Yes | CommonJS |
| TypeScript types | Bundled | DefinitelyTyped |
| 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 need active maintenance and bug fixes.
- Your UI depends on modern CSS features (variables, pseudo-elements, line-clamp).
- You use Web Components or Shadow DOM.
- You want to add custom export formats or transformations through plugins.
- You need first-class TypeScript types out of the box.
Check before migrating…
- Compare captures of your layouts in each browser you support.
- Test web fonts, open Shadow DOM, CSS counters and line-clamp with your content.
- CommonJS-era packaging and no bundled TypeScript types.
Same task, side by side
Capturing #card as a PNG and inserting the resulting image into the page:
dom-to-image
import domtoimage from 'dom-to-image'; const dataUrl = await domtoimage.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);
SnapDOM returns the HTMLImageElement directly so you can drop the data-URL plumbing.
Migration snippet
Match both the output format and return type. A dom-to-image filter includes nodes when true; SnapDOM exclude removes them when true. SnapDOM width and height size the output rather than reflowing the source layout:
| dom-to-image | SnapDOM |
|---|---|
| domtoimage.toPng(el) | (await snapdom.toPng(el)).src |
| domtoimage.toJpeg(el, { quality: 0.9 }) | (await snapdom.toJpg(el, { quality: 0.9 })).src |
| domtoimage.toBlob(el) | snapdom.toBlob(el, { format: 'png' }) |
| domtoimage.toSvg(el) | snapdom.toRaw(el) |
| { bgcolor: '#fff' } | { backgroundColor: '#fff' } |
| { width, height } | { width, height } (output size) |
| { filter: keep } | { exclude: node => !keep(node) } |
| — (not supported) | { embedFonts: 'auto' } (default) |
| — (not supported) | { plugins: [...] } |
// Before import domtoimage from 'dom-to-image'; const dataUrl = await domtoimage.toPng(el, { bgcolor: '#fff' }); // After import { snapdom } from '@zumer/snapdom'; const img = await snapdom.toPng(el, { backgroundColor: '#fff' });
Frequently asked questions
Is dom-to-image still maintained?
Check the dom-to-image repository for its release history and open issues. Before migrating, compare your captured output and account for the return-type and option differences shown above.
How do I migrate from dom-to-image to SnapDOM?
Import @zumer/snapdom and start with snapdom.toPng(element). Read .src on the returned image if the caller expects a PNG data URL. Rename bgcolor to backgroundColor, invert inclusion predicates for exclude, and review output sizing.
Does SnapDOM support custom fonts?
Yes. In v3, embedFonts: 'auto' embeds used web fonts by default. Font files must be accessible; localFonts and excludeFonts give additional control.
What about Shadow DOM?
Open Shadow DOM trees are walked and cloned by SnapDOM, so Web Components capture correctly. dom-to-image does not natively support this.
Ready to switch?
Drop SnapDOM into your project and capture your first element in seconds.
Open the demo Installation