Package Exports
- @zumer/snapdom
Readme
snapDOM
snapDOM is a fast and accurate DOM capture tool to images developed for Zumly, a WIP framework that enables zoom-based view transitions.
It converts any HTML element into a scalable SVG image, preserving styles, fonts, backgrounds, shadow DOM content, pseudo-elements, and more.
- πΈ 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
Installation
You can use snapDOM via NPM, CDN, script tag, or by importing as a module.
NPM / Yarn
npm i @zumer/snapdomyarn add @zumer/snapdomCDN
<script src="https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.min.js"></script>Script tag (local)
<script src="snapdom.js"></script>The global object snapdom will be available.
ES Module
import { snapdom } from './snapdom.mjs';Script Tag (Type Module)
<script type="module">
import { snapdom } from 'https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.mjs';
</script>Now you can call snapdom(el), snapdom.toPng(el), etc., directly in your JavaScript.
Basic usage
// Capture an element as <img> tag
const el = document.querySelector("#myElement")
const img = await snapdom.toImg(el);
document.body.appendChild(img);API
Note: API may evolve until v1.0.0!
The main API is exposed as snapdom and offers multiple capture methods:
| Method | Description |
|---|---|
snapdom(el, options?) |
Captures as SVG Data URL |
snapdom.toImg(el, options?) |
Captures as HTMLImageElement (SVG) |
snapdom.toCanvas(el, options?) |
Captures as HTMLCanvasElement |
snapdom.toPng(el, options?) |
Captures as PNG image (Image) |
snapdom.toJpg(el, options?) |
Captures as JPG image (Image) |
snapdom.toWebp(el, options?) |
Captures as WebP image (Image) |
snapdom.toBlob(el, options?) |
Captures as SVG Blob |
preCache(root?, options?) |
Preload resources for faster and more accurate captures |
Options
You can pass an options object to control the behavior of all capture methods:
| Option | Type | Default | Description |
|---|---|---|---|
compress |
boolean |
true |
Removes default styles to reduce size and deduplicate CSS where possible. |
fast |
boolean |
true |
Skips requestIdleCallback delays and executes preparation immediately. |
embedFonts |
boolean |
false |
Inlines external fonts as Data URLs (except icon fonts, which are always embedded). |
scale |
number |
1 |
Multiplies the output resolution without affecting layout size. |
backgroundColor |
string |
"#fff" |
Used when exporting to JPG or WebP formats (which don't support transparency). |
quality |
number |
1 |
Compression quality for JPG/WebP, between 0 and 1. |
preCache() β Optional helper
The preCache() function can be used to load external resources (like images and fonts) in advance.
import { preCache } from '@zumer/snapdom';
await preCache(document.body, {
embedFonts: true,
preWarm: true
});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.preWarm(boolean, default: true) β Runs a fake capture in memory to warm up styles, fonts and layout detection.
Special features
Shadow DOM: Captures content inside Web Components and
shadowRoot.Pseudo-elements: Captures
::beforeand::after, including background images.Backgrounds and images: Inlines external images as Data URLs.
Fonts: Replicates applied font families without requiring external font files.
Icon fonts: Captures icon fonts like Font Awesome and Material Icons.
Placeholder and Exclusion:
data-capture="exclude": Skips an element while preserving layout space.data-capture="placeholder"+data-placeholder-text="Text": Replaces an element with placeholder text.
Now with improved fidelity and even faster performance.
Full example
<div id="captureMe">
<h1 style="color: tomato;">Hello World!</h1>
<p>This content will be captured.</p>
</div>
<button id="captureBtn">Capture as img</button>
<script type="module">
import { snapdom } from './snapdom.mjs';
const button = document.getElementById('captureBtn');
button.addEventListener('click', async () => {
const target = document.getElementById('captureMe');
const img = await snapdom.toJpg(target, { quality: 0.5});
document.body.appendChild(img);
});
</script>Limitations
- External images must be CORS-accessible.
- Iframes are not captured.
Please if you find a bug open an issue.
Benchmarks
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 |
Run the benchmarks
To run these benchmarks yourself:
git clone https://github.com/zumerlab/snapdom.git
cd snapdom
npm install
npm run test:benchmarkThey execute in headless Chromium using real DOM nodes.
License
MIT Β© Zumerlab