SnapDOMGitHub★ 8K
Library Comparison
zumerlab/snapdom …

SnapDOM vs modern-screenshot

Two modern libraries, the same core idea: clone the DOM and let the browser render it inside an SVG <foreignObject>. Here's where they actually differ — and how to move between them.

Feature matrix Migration map
TL;DR

Both libraries render cloned DOM through foreignObject and export SVG, PNG, JPEG, WebP, Canvas and Blob. modern-screenshot has a TypeScript API. SnapDOM also provides a plugin system for HTML, structured context and maps, PDF images, GIF and video. Both are MIT-licensed.

SnapDOM vs modern-screenshot, 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.

Test element to be captured by both libraries.
SnapDOM
Waiting to start…
modern-screenshot
Waiting to start…

Same approach, different scope

modern-screenshot and SnapDOM belong to the same family as html-to-image: instead of re-implementing the CSS painter the way html2canvas does, they deep-clone the DOM, inline styles/fonts/images, and wrap the clone in an SVG <foreignObject> so the browser performs the actual render. The shared rendering approach does not guarantee identical output or timing; test the content and browsers you use.

The core output formats overlap. SnapDOM exposes an extensible capture and export lifecycle, with official plugins for additional representations and transformations. Both libraries have browser-specific rendering behavior to check on complex pages.

Feature matrix

FeatureSnapDOMmodern-screenshot
Rendering approachClone + foreignObjectClone + foreignObject
Output formatsSVG · PNG · JPG · WebP · Canvas · BlobPNG · JPEG · WebP · SVG · Canvas · Blob
Plugin systemYesNo
Web fonts (@font-face)EmbeddedYes
Pseudo-elementsYesYes
Shadow DOMOpen rootsOpen roots
TypeScript-first APITyped, JS coreYes
Runtime dependencies00
MaintainedActiveActive
LicenseMITMIT

Feature support in other libraries evolves — for anything version-specific, check their docs for the latest. Or run the live benchmark above and compare the output yourself.

When to use which

Choose SnapDOM when…

  • You want to extend capture with plugins (watermarks, filters, custom exporters, PDF…).
  • Your UI uses Shadow DOM / Web Components and you need them captured reliably.
  • You hit edge cases (Safari rendering, complex @font-face, counters, line-clamp) and want them already handled.
  • You want one API spanning SVG, PNG, JPG, WebP, Canvas and Blob.

Check your existing workflow…

  • Decide whether post-processing or capture lifecycle hooks suit your transformations.
  • Test your Web Components in the browsers you support.
  • Compare Safari output and complex @font-face setups with your assets.
  • Core image formats overlap; optional SnapDOM plugins add HTML, context, PDF and animation exports.

Same task, side by side

Capturing #card as a PNG and inserting the resulting image into the page:

modern-screenshot

import { domToPng } from 'modern-screenshot';

const dataUrl = await domToPng(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);

modern-screenshot's domToPng resolves to a data-URL string; SnapDOM's toPng resolves to a ready-to-append HTMLImageElement. For a PNG data URL, read (await snapdom.toPng(el)).src. snapdom.toRaw(el) returns an SVG data URL.

Migration map

Check the format and return type at each call site. SnapDOM image helpers return HTMLImageElement; read .src for a data URL. Its default Blob format is SVG, so request PNG explicitly when migrating a PNG Blob export.

modern-screenshotSnapDOM
domToPng(node)(await snapdom.toPng(node)).src
domToJpeg(node)(await snapdom.toJpg(node)).src
domToWebp(node)(await snapdom.toWebp(node)).src
domToSvg(node)snapdom.toRaw(node)
domToCanvas(node)snapdom.toCanvas(node)
domToBlob(node)snapdom.toBlob(node, { format: 'png' })

Frequently asked questions

Is SnapDOM or modern-screenshot faster?

Timing depends on the element, assets, browser and whether the capture is fresh or repeated. Use the live benchmark with its displayed library versions, then test both libraries on your own content.

What does SnapDOM offer that modern-screenshot doesn't?

SnapDOM has a plugin lifecycle and official plugins for portable HTML, structured context and maps, PDF images, GIF and video. The two libraries share the core SVG, raster image, Canvas and Blob output formats.

Can I migrate from modern-screenshot without rewriting everything?

Common exports have equivalents, but return types and options need review. For a PNG string use (await snapdom.toPng(el)).src; snapdom.toRaw(el) returns SVG. Request format: 'png' when a Blob consumer expects PNG.

Are both libraries free for commercial use?

Yes. SnapDOM and modern-screenshot are MIT-licensed. Neither library charges a per-capture fee or requires a screenshot server.

Try SnapDOM on your page

Capture a rendered element as PNG, SVG or Canvas. Add other exports through plugins.

Open the demo Installation