DEV Community

Juan Martin
Juan Martin

Posted on

Snapdom: a modern and faster alternative to html2canvas

In less than two months, Snapdom reached 2,120+ stars, with 7 contributors and a growing user base. But the goal has been clear since day one:

Build a modern, accurate and fast replacement for html2canvas.

Why a replacement?

html2canvas was a milestone. I love it. It brought DOM-to-image to mainstream frontend. But time has passed, and the web platform has evolved: higher DPI screens, complex shadows, pseudo-elements with ::before { content: url(...) }, imported icon fonts, variables inside gradients, shadow DOM, web components, and more.

Many of those features don’t render correctly in html2canvas. Snapdom aims to fix that with a new approach.

Benchmark


What Snapdom does differently

Snapdom captures how a DOM looks. While tools like html2canvas attempt to reproduce the layout procedurally using canvas drawing commands, Snapdom takes a different route:

  • It builds a visual clone of the DOM using a serialized structure and renders it via SVG with <foreignObject>.
  • Styles are computed via getComputedStyle() and inlined per element, or collapsed into reusable CSS classes when compress mode is enabled.
  • Snapdom uses caching strategies for computed styles, fonts, and DOM shape to improve render performance.
  • It supports hi-DPI scaling, fixed size snapshots, and consistent box models across browsers.

This approach makes it fast, modular, and portable — and allows Snapdom to produce SVG output that can be rendered, embedded, or exported in almost any format.

Visual fidelity

  • Captures ::before / ::after / ::first-letter, including icons, URLs and inline content.
  • Supports background-image with multiple layers: url(), linear-gradient(...), var(...), mixed.
  • Handles shadows, filters, transforms, blend modes, scroll, overflow, and z-index correctly.
  • Captures shadow DOM content and visual order.

Fonts and icon support

  • Full support for @font-face via stylesheets or FontFace() constructor.
  • Correct rendering of icon fonts (FontAwesome, Material Icons, etc.) — including inside pseudo-elements.
  • embedFonts: true will inline all fonts into the SVG.

DOM state

  • Captures current values of inputs, selects, and textareas.
  • Preserves scroll position (scrollTop, scrollLeft).
  • HiDPI / Retina support via devicePixelRatio.
  • Optional fixed dimensions with width and/or height.
await snapdom(el, {
  width: 1024,
  height: 768,
  embedFonts: true,
  compress: true,
});
Enter fullscreen mode Exit fullscreen mode

Performance-focused

  • Snapshots in milliseconds, even on complex pages.
  • One-time capture → multiple exports:
const result = await snapdom(el);
await result.toSvg();
await result.toPng();
await result.toWebp({ backgroundColor: "#fff" });
Enter fullscreen mode Exit fullscreen mode

Coming soon: Plugin system

We're working on a native plugin architecture so anyone can extend Snapdom with custom needs.

Some ideas:

  • Watermarking
  • PDF export
  • WebGL / canvas integration
  • Post-capture mutation (blurring, tinting, overlays, etc.)
  • Integration with visual editors

The plugin API will allow users to hook into preprocessing, postprocessing, and export logic.


API at a glance

const result = await snapdom(el, {
  scale: 2,
  compress: true,
  embedFonts: true,
  backgroundColor: "#fff",
  crossOrigin: "anonymous",
});

// Exports
await result.toSvg();
await result.toCanvas();
await result.toPng();
await result.toWebp();
await result.toImg();
Enter fullscreen mode Exit fullscreen mode
  • data-capture="exclude" skips a node and its children.
  • data-capture="placeholder" replaces a node with an empty box (useful for ads, iframes, etc).

Try it

📦 GitHub → github.com/zumerlab/snapdom
🧪 Live demo → zumerlab.github.io/snapdom

Snapdom is fully browser-based. No canvas hacks, no server dependency. Just clean JS + SVG + Web APIs.

We're actively looking for feedback and contributors. If you're hitting limits with html2canvas, try Snapdom and help shape its future.

Top comments (0)