An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

          

# snapDOM







NPM version


GitHub contributors


GitHub stars


GitHub forks


License

**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 πŸ™Œ


tinchox5
pedrocateexte
domialex
elliots
jswhisperer
jhbae200

## License

MIT Β© Zumerlab