Library Comparison
zumerlab/snapdom

SnapDOM vs dom-to-image

An honest look at the original DOM-to-image library and a modern, maintained alternative built around the same idea.

Feature matrix Migration snippet
TL;DR

dom-to-image was the first library to popularise the SVG foreignObject trick for capturing the DOM, but its original package hasn't been actively maintained for years. SnapDOM picks up the same approach, modernises it, and adds web fonts, Shadow DOM, plugins and full pseudo-element support.

A quick overview

dom-to-image introduced the technique most modern libraries still use: clone the node, inline its CSS and assets, wrap it in a <foreignObject>, and let the browser do the painting. It works, it's small, and the API is friendly. The downside is that it stopped receiving meaningful updates, so newer CSS features and edge cases are gradually catching up to it.

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 transform the result without forking the library.

Feature matrix

FeatureSnapDOMdom-to-image
Active maintenanceYesStalled
Pseudo-elements (::before / ::after)FullLimited
Web fonts (@font-face)EmbeddedBest-effort
Shadow DOMYesNo
CSS variablesYesPartial
CSS counter() / counters()YesNo
Line-clamp / multi-line ellipsisYesNo
Plugin systemYesNo
Output formatsSVG · PNG · JPG · WebP · Canvas · BlobSVG · PNG · JPG · Blob
ES Module buildYesCommonJS
TypeScript typesBundledDefinitelyTyped
LicenseMITMIT

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.

dom-to-image might still fit when…

  • You're maintaining a legacy CommonJS project that's already using it and works fine.
  • Your captures are simple and you prefer not to introduce any new dependencies.

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

Most dom-to-image options have a direct SnapDOM equivalent:

dom-to-imageSnapDOM
domtoimage.toPng(el)snapdom.toPng(el)
domtoimage.toJpeg(el, { quality: 0.9 })snapdom.toJpg(el, { quality: 0.9 })
domtoimage.toBlob(el)snapdom.toBlob(el)
domtoimage.toSvg(el)(await snapdom(el)).toSvg()
{ bgcolor: '#fff' }{ backgroundColor: '#fff' }
{ width, height }{ width, height }
{ filter: node => … }{ filter: node => … }
— (not supported){ embedFonts: true }
— (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?

The original dom-to-image package on npm has not received a release in years. The community-maintained fork dom-to-image-more is more active, and html-to-image is another popular fork. SnapDOM is a from-scratch alternative under active development.

How do I migrate from dom-to-image to SnapDOM?

Replace the import with @zumer/snapdom and call snapdom.toPng(element). Most options (filter, bgcolor, width, height, style) have a direct SnapDOM equivalent — see the migration table above.

Does SnapDOM support custom fonts?

Yes. Pass { embedFonts: true } and the matching @font-face declarations are inlined into the SVG output, so the captured image renders with your real fonts.

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 Install from npm