zumerlab/snapdom
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,
canvas, or Blob - β‘ Ultra fast, no dependencies
- π¦ 100% based on standard Web APIs
Demo
https://zumerlab.github.io/snapdom/
Installation
NPM / Yarn
|
|
|
|
Then import it in your code:
|
|
CDN
|
|
Script tag (local)
|
|
ES Module
|
|
Module via CDN
|
|
Basic usage
Reusable capture
|
|
One-step shortcuts
|
|
API
snapdom(el, options?)
Returns an object with reusable export methods:
|
|
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 |
dpr |
number | devicePixelRatio |
Device pixel ratio |
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.
|
|
2. Fixed height (proportional width) Sets a specific height while maintaining the aspect ratio. Width adjusts proportionally.
|
|
3. Fixed width and height (may distort image) Forces exact dimensions, potentially distorting the image if the aspect ratio differs.
|
|
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:
|
|
Download options
|
|
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 capture is big and complex.
|
|
|
|
Options for preCache():
embedFonts(boolean, default: true) β Inlines non-icon fonts during preload.useProxy(string) β Proxy for handling CORS images as fallback.
Features
- Captures shadow DOM and Web Components
- Supports
::before,::afterand::first-letterpseudo-elements - Inlines background images and fonts
- Handles Font Awesome, Material Icons, and more
data-capture="exclude"to ignore an elementdata-capture="placeholder"withdata-placeholder-textfor masked replacements
Limitations
- External images should be CORS-accessible (use
useProxyoption for handling CORS denied) - Iframes are not supported
- When WebP format is used on Safari, it will fallback to PNG rendering.
@font-faceCSS rule is well supported, but if need to use JSFontFace(), 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
html2canvashtml-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-imagein large scenarios
Benchmarks run in Chromium using Vitest.
Hardware: MacBook Air 2018.
β οΈ Performance may vary depending on device.
Run the benchmarks
|
|
Roadmap
Planned improvements for future versions of SnapDOM:
-
Implement plugin system SnapDOM will support external plugins to extend or override internal behavior (e.g. custom node transformers, exporters, or filters).
-
Refactor to modular architecture Internal logic will be split into smaller, focused modules to improve maintainability and code reuse.
-
Decouple internal logic from global options Functions will be redesigned to avoid relying directly on
options. A centralized capture context will improve clarity, autonomy, and testability. Seenextbranch -
Expose cache control Users will be able to manually clear image and font caches or configure their own caching strategies.
-
Auto font preloading Required fonts will be automatically detected and preloaded before capture, reducing the need for manual
preCache()calls. -
Document plugin development A full guide will be provided for creating and registering custom SnapDOM plugins.
-
Make export utilities tree-shakeable Export functions like
toPng,toJpg,toBlob, etc. will be restructured into independent modules to support tree shaking and minimal builds.
Have ideas or feature requests? Feel free to share suggestions or feedback in GitHub Discussions.
Development
To contribute or build snapDOM locally:
|
|
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.
Star History
License
MIT Β© Zumerlab