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
https://zumerlab.github.io/snapdom/
npm i @zumer/snapdom
yarn add @zumer/snapdom
<script src="https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.min.js"></script>
<script src="snapdom.js"></script>
import { snapdom } from './snapdom.mjs';
<script type="module">
import { snapdom } from 'https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.mjs';
</script>
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' });
const el = document.querySelector('#target');
const png = await snapdom.toPng(el);
document.body.appendChild(png);
const blob = await snapdom.toBlob(el);
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>;
}
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 |
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 |
backgroundColor |
string | "#fff" |
Fallback color for JPG/WebP |
quality |
number | 1 |
Quality for JPG/WebP (0 to 1) |
{
format?: "svg" | "png" | "jpg" | "jpeg" | "webp"; // default: "png"
filename?: string; // default: "capture"
backgroundColor?: string; // optional override
}
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.
- Captures shadow DOM and Web Components
- Supports
::before
and::after
pseudo-elements - Inlines background images and fonts
- Handles Font Awesome, Material Icons, and more
data-capture="exclude"
to ignore an elementdata-capture="placeholder"
withdata-placeholder-text
for masked replacements
- External images must be CORS-accessible
- Iframes are not supported
- When WebP format is used on Safari, it will fallback to PNG rendering.
snapDOM
is not only highly accurate β itβs extremely fast.
Latest benchmarks show significant performance improvements against other libraries:
Scenario | vs. modern-screenshot |
vs. html2canvas |
---|---|---|
Small element (200Γ100) | 6.46Γ faster | 32.27Γ faster |
Modal size (400Γ300) | 7.28Γ faster | 32.66Γ faster |
Page view (1200Γ800) | 13.17Γ faster | 35.29Γ faster |
Large scroll area (2000Γ1500) | 38.23Γ faster | 68.85Γ faster |
Very large element (4000Γ2000) | 93.31Γ faster | 133.12Γ faster |
Complex small element (200Γ100) | 3.97Γ faster | 15.23Γ faster |
Complex modal (400Γ300) | 2.32Γ faster | 5.33Γ faster |
Complex page (1200Γ800) | 1.62Γ faster | 1.65Γ faster |
Complex large scroll (2000Γ1500) | 1.66Γ faster | 1.24Γ faster |
Complex very large (4000Γ2000) | 1.52Γ faster | 1.28Γ faster |
To run these benchmarks yourself:
git clone https://github.com/zumerlab/snapdom.git
cd snapdom
npm install
npm run test:benchmark
They execute in headless Chromium using real DOM nodes.
MIT Β© Zumerlab