https://github.com/zumerlab/snapdom
snapDOM captures DOM elements as images with exceptional speed and minimal overhead. Designed to avoid bottlenecks and long tasks.
https://github.com/zumerlab/snapdom
Last synced: 7 months ago
JSON representation
snapDOM captures DOM elements as images with exceptional speed and minimal overhead. Designed to avoid bottlenecks and long tasks.
- Host: GitHub
- URL: https://github.com/zumerlab/snapdom
- Owner: zumerlab
- License: mit
- Created: 2025-04-27T11:01:19.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-04-27T11:01:19.000Z (9 months ago)
- Last Synced: 2025-04-27T11:39:56.897Z (9 months ago)
- Size: 0 Bytes
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- StarryDivineSky - zumerlab/snapdom
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/](https://zumerlab.github.io/snapdom/)
## Installation
### NPM / Yarn
```sh
npm i @zumer/snapdom
```
```sh
yarn add @zumer/snapdom
```
### CDN
```html
```
### Script tag (local)
```html
```
### ES Module
```js
import { snapdom } from './snapdom.mjs';
```
### Module via CDN
```html
import { snapdom } from 'https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.mjs';
```
## Basic usage
### Reusable capture
```js
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
```js
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:
```js
{
url: string;
toRaw(): string;
toImg(): Promise;
toCanvas(): Promise;
toBlob(): Promise;
toPng(): Promise;
toJpg(options?): Promise;
toWebp(options?): Promise;
download(options?): Promise;
}
```
### 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 |
| `backgroundColor` | string | `"#fff"` | Fallback color for JPG/WebP |
| `quality` | number | `1` | Quality for JPG/WebP (0 to 1) |
| `crossOrigin` | function | - | Function to determine CORS mode per image URL |
### Cross-Origin Images
By default, snapDOM loads images with `crossOrigin="anonymous"`. You can customize this behavior using the `crossOrigin` option:
```js
const result = await snapdom(element, {
crossOrigin: (url) => {
// Use credentials for same-origin images
if (url.startsWith(window.location.origin)) {
return "use-credentials";
}
// Use anonymous for cross-origin images
return "anonymous";
}
});
```
This is useful when your images require authentication or when dealing with credentialed requests.
### Download options
```js
{
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.
```js
import { preCache } from '@zumer/snapdom';
await preCache(document.body);
```
```js
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.
* `crossOrigin` *(function)* β Function to determine CORS mode per image URL during preload.
## Features
* 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 element
* `data-capture="placeholder"` with `data-placeholder-text` for masked replacements
## Limitations
* External images must be CORS-accessible (use `crossOrigin` option for credentialed requests)
* 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`](https://github.com/zumerlab/snapdom/issues/43)
## 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:
```sh
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.
## Development
To contribute or build snapDOM locally:
```sh
# Clone the repository
git clone https://github.com/zumerlab/snapdom.git
cd snapdom
# Install dependencies
npm install
# Compile the library (ESM, CJS, and minified versions)
npm run compile
# 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](https://github.com/zumerlab/snapdom/blob/main/CONTRIBUTING.md).
## Contributors π
## License
MIT Β© Zumerlab