npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mindblowing/snapdom

v1.9.9

Published

snapDOM captures HTML elements to images with exceptional speed and accuracy.

Readme

snapDOM

snapDOM is a fast and accurate DOM-to-image capture tool built for Zumly, a zoom-based view transition framework.

It captures any HTML element as a scalable SVG image, preserving styles, fonts, background images, pseudo-elements, and even shadow DOM. It also supports export to raster image formats and canvas.

  • 📸 Full DOM capture
  • 🎨 Embedded styles, pseudo-elements, and fonts
  • 🖼️ Export to SVG, PNG, JPG, WebP, or canvas
  • ⚡ Ultra fast, no dependencies
  • 📦 100% based on standard Web APIs

Demo

https://zumerlab.github.io/snapdom/

Installation

NPM / Yarn

npm i @zumer/snapdom
yarn add @zumer/snapdom

CDN

<script src="https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.min.js"></script>

Script tag (local)

<script src="snapdom.js"></script>

ES Module

import { snapdom } from './snapdom.mjs';

Module via CDN

<script type="module">
  import { snapdom } from 'https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.mjs';
</script>

Basic usage

Reusable capture

const el = document.querySelector('#target');
const result = await snapdom(el, { scale: 2 });

const img = await result.toPng();
document.body.appendChild(img);

await result.download({ format: 'jpg', filename: 'my-capture' });

One-step shortcuts

const el = document.querySelector('#target');
const png = await snapdom.toPng(el);
document.body.appendChild(png);

const blob = await snapdom.toBlob(el);

API

snapdom(el, options?)

Returns an object with reusable export methods:

{
  url: string;
  toRaw(): string;
  toImg(): Promise<HTMLImageElement>;
  toCanvas(): Promise<HTMLCanvasElement>;
  toBlob(): Promise<Blob>;
  toPng(): Promise<HTMLImageElement>;
  toJpg(options?): Promise<HTMLImageElement>;
  toWebp(options?): Promise<HTMLImageElement>;
  download(options?): Promise<void>;
}

Shortcut methods

| Method | Description | | ------------------------------ | ------------------------------------- | | snapdom.toImg(el, options?) | Returns an HTMLImageElement | | snapdom.toCanvas(el, options?) | Returns a Canvas | | snapdom.toBlob(el, options?) | Returns an SVG Blob | | snapdom.toPng(el, options?) | Returns a PNG image | | snapdom.toJpg(el, options?) | Returns a JPG image | | snapdom.toWebp(el, options?) | Returns a WebP image | | snapdom.download(el, options?) | Triggers download in specified format |

Options

All capture methods accept an options object:

| Option | Type | Default | Description | | ----------------- | -------- | -------- | ------------------------------------------ | | compress | boolean | true | Removes redundant styles | | fast | boolean | true | Skips idle delay for faster results | | embedFonts | boolean | false | Inlines fonts (icon fonts always embedded) | | scale | number | 1 | Output scale multiplier | | width | number | - | Output specific width size | | height | number | - | Output specific height size | | backgroundColor | string | "#fff" | Fallback color for JPG/WebP | | quality | number | 1 | Quality for JPG/WebP (0 to 1) | | useProxy | string | '' | Specify a proxy for handling CORS images as fallback| | type | string | svg | Select png, jpg, webp Blob type| | exclude | string[] | - | CSS selectors for elements to exclude | | filter | function | - | Custom filter function ie (el) => !el.classList.contains('hidden') |

Setting custom dimensions with width and height options

Use the width and height options to generate an image with specific dimensions.

Examples:

1. Fixed width (proportional height) Sets a specific width while maintaining the aspect ratio. Height adjusts proportionally.

const result = await snapdom(element, {
  width: 400 // Outputs a 400px-wide image with auto-scaled height
});

2. Fixed height (proportional width) Sets a specific height while maintaining the aspect ratio. Width adjusts proportionally.

const result = await snapdom(element, {
  height: 200 // Outputs a 200px-tall image with auto-scaled width
});

3. Fixed width and height (may distort image) Forces exact dimensions, potentially distorting the image if the aspect ratio differs.

const result = await snapdom(element, {
  width: 800,  // Outputs an 800px × 200px image (may stretch/squish content)
  height: 200
});

Note: If scale is different from 1, it takes priority over width and height. Example: { scale: 3, width: 500 } ignores width and scales the image 3x instead.

Cross-Origin Images

By default, snapDOM loads images with crossOrigin="anonymous" or crossOrigin="use-credentials". In case fails to get the images, useProxy can be used to deal with CORS images:

const result = await snapdom(element, {
  useProxy: 'your/proxy/' //Example: 'https://corsproxy.io/?url=' or 'https://api.allorigins.win/raw?url='
});

Download options

{
  format?: "svg" | "png" | "jpg" | "jpeg" | "webp"; // default: "png"
  filename?: string;         // default: "capture"
  backgroundColor?: string;  // optional override
}

preCache() – Optional helper

The preCache() function can be used to load external resources (like images and fonts) in advance. It is specially useful when the element to capure is big and complex.

import { preCache } from '@zumer/snapdom';

await preCache(document.body);
import { snapdom, preCache } from './snapdom.mjs';
    window.addEventListener('load', async () => {
    await preCache();
    console.log('📦 Resources preloaded');
    });

Options for preCache():

  • embedFonts (boolean, default: true) — Inlines non-icon fonts during preload.
  • reset (boolean, default: false) — Clears all existing internal caches.
  • useProxy (string) — Proxy for handling CORS images as fallback.

Features

  • Captures shadow DOM and Web Components
  • Supports ::before, ::after and ::first-letter pseudo-elements
  • Inlines background images and fonts
  • Handles Font Awesome, Material Icons, and more
  • data-capture="exclude" to ignore an element
  • data-capture="placeholder" with data-placeholder-text for masked replacements

Limitations

  • External images shloud be CORS-accessible (use useProxy option for handling CORS denied)
  • Iframes are not supported
  • When WebP format is used on Safari, it will fallback to PNG rendering.
  • @font-face CSS rule is well supported, but if need to use JS FontFace(), see this workaround #43

⚡ Performance Benchmarks

Snapdom has received significant performance improvements since version v1.8.0. The following benchmarks compare:

  • Snapdom (current)
  • Snapdom v1.8.0
  • html2canvas
  • html-to-image

Simple elements

| Scenario | Snapdom (current) | Snapdom v1.8.0 | html2canvas | html-to-image | | ------------------------ | ----------------- | -------------- | ----------- | ------------- | | Small (200×100) | 0.4 ms | 1.2 ms | 70.3 ms | 3.6 ms | | Modal (400×300) | 0.4 ms | 1.1 ms | 68.8 ms | 3.6 ms | | Page View (1200×800) | 0.4 ms | 1.0 ms | 100.5 ms | 3.4 ms | | Large Scroll (2000×1500) | 0.4 ms | 1.0 ms | 153.1 ms | 3.4 ms | | Very Large (4000×2000) | 0.4 ms | 1.0 ms | 278.9 ms | 4.3 ms |

Complex elements

| Scenario | Snapdom (current) | Snapdom v1.8.0 | html2canvas | html-to-image | | ------------------------ | ----------------- | -------------- | ----------- | ------------- | | Small (200×100) | 1.1 ms | 3.2 ms | 76.0 ms | 15.3 ms | | Modal (400×300) | 4.5 ms | 14.0 ms | 133.2 ms | 55.4 ms | | Page View (1200×800) | 32.9 ms | 113.6 ms | 303.4 ms | 369.1 ms | | Large Scroll (2000×1500) | 133.9 ms | 387.4 ms | 594.4 ms | 1,163.0 ms | | Very Large (4000×2000) | 364.0 ms | 1,200.4 ms | 1,380.8 ms | 3,023.9 ms |

Summary

  • Snapdom (current) is 2×–6× faster than v1.8.0
  • Up to 150× faster than html2canvas
  • Up to 8× faster than html-to-image in large scenarios

Benchmarks run in Chromium using Vitest. Hardware: MacBook Air 2018. ⚠️ Performance may vary depending on device.

Run the benchmarks

git clone https://github.com/zumerlab/snapdom.git
cd snapdom
npm install
npm run test:benchmark

Development

To contribute or build snapDOM locally:

# Clone the repository
git clone https://github.com/zumerlab/snapdom.git
cd snapdom

# Switch to dev branch
git checkout dev

# Install dependencies
npm install

# Compile the library (ESM, CJS, and minified versions)
npm run compile

# Install playwright browsers (necessary for running tests)
npx playwright install

# Run tests
npm test

# Run Benchmarks
npm run test:benchmark

The main entry point is in src/, and output bundles are generated in the dist/ folder.

For detailed contribution guidelines, please see CONTRIBUTING.

Contributors 🙌

💖 Sponsors

Special thanks to @megaphonecolin for supporting this project!

If you'd like to support this project too, you can become a sponsor.

License

MIT © Zumerlab