# snapDOM: A Fast and Accurate Tool for Converting Web Elements to Images
In modern web development and design, there’s often a need to save a part of a webpage—a chart, a component, or even the whole page—as an image. This might be for sharing, reports, or documentation. While taking a screenshot is the most direct way, it often falls short when you need high quality, precise control, or automation. This is where tools like snapDOM become invaluable.
snapDOM is a JavaScript library designed for modern web development. Its core function is to quickly and accurately capture any HTML element and convert it into an image. It’s more than just a simple screenshot tool; it’s a powerful and easy-to-integrate solution, especially suited for scenarios requiring high-quality, high-fidelity image output.
## What is snapDOM?
Put simply, snapDOM is a JavaScript library whose primary function is to capture any HTML element on a webpage (including its styles, fonts, background images, and even Shadow DOM) and convert it into an image. It supports exporting to multiple formats, including scalable SVG as well as common formats like PNG, JPG, and WebP. It can also directly output to a <canvas>
element.
This tool was initially developed for a view transition framework called Zumly, but its design is very general-purpose, making it easy to apply in various projects.
## Why Choose snapDOM?
Among the many tools available for converting DOM to images, snapDOM stands out due to its unique advantages:
-
Fast and Accurate: snapDOM is optimized for speed. Its performance, especially when dealing with complex elements, significantly outperforms many similar tools (we’ll provide detailed comparisons later). -
High Fidelity: It accurately captures the element’s appearance, including embedded styles, pseudo-elements (like ::before
and::after
), fonts, and background images, ensuring the generated image matches what you see on the webpage. -
Supports Modern Web Technologies: snapDOM can handle Shadow DOM and Web Components, which is crucial for applications built with modern frontend frameworks like Vue, React, and Angular. -
No Dependencies, Built on Standards: It doesn’t rely on any third-party libraries and is built entirely using standard Web APIs provided by browsers, ensuring it’s lightweight and has good compatibility. -
Flexible Export Options: It provides multiple convenient methods to convert the capture result directly into an <img>
tag, a<canvas>
, or aBlob
object. It also supports one-click downloading in a specified file format. -
Easy to Use: Whether you install it via NPM or include it directly with a <script>
tag, integrating snapDOM is very straightforward. Its API design is also intuitive and easy to understand.
## How to Install snapDOM?
Integrating snapDOM into your project is very simple. It supports several mainstream methods of inclusion:
### Using NPM or Yarn (Recommended for Modular Projects)
If your project uses NPM or Yarn for package management, this is the most recommended approach.
# Using NPM
npm install @zumer/snapdom
# Using Yarn
yarn add @zumer/snapdom
### Via CDN (Suitable for Rapid Prototyping or Simple Pages)
If you don’t want to configure a build tool, you can include it directly via a CDN link.
<!-- Include the minified JS file -->
<script src="https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.min.js"></script>
Or, if your project uses ES modules:
<script type="module">
import { snapdom } from 'https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.mjs';
</script>
### Local Script Inclusion
You can also download the snapDOM files locally and include them using a <script>
tag.
<!-- Assuming snapdom.js file is in your project directory -->
<script src="snapdom.js"></script>
For ES modules:
// Assuming snapdom.mjs file is in your project directory
import { snapdom } from './snapdom.mjs';
## How to Use snapDOM?
Using snapDOM is very intuitive. It provides a core snapdom
function, along with a series of convenient shortcut methods.
### Basic Usage: Reusable Capture Result
This is the most flexible way to use it, suitable for scenarios where you need to perform multiple different operations on the capture result.
// 1. Select the HTML element you want to capture
const elementToCapture = document.querySelector('#target');
// 2. Call the snapdom function, passing the element and optional configuration options
// This returns an object containing various export methods
const captureResult = await snapdom(elementToCapture, { scale: 2 });
// 3. Use the returned object to perform actions
// For example, convert it to a PNG image and insert it into the page
const imgElement = await captureResult.toPng();
document.body.appendChild(imgElement);
// Or, trigger a download directly
await captureResult.download({ format: 'jpg', filename: 'my-capture' });
### One-Step Shortcut Methods
If you only need to quickly generate and use an image in one specific format, snapDOM provides more concise shortcut methods.
// Select the target element
const el = document.querySelector('#target');
// Generate a PNG image directly and insert it into the page
const pngImage = await snapdom.toPng(el);
document.body.appendChild(pngImage);
// Generate a Blob object directly
const blob = await snapdom.toBlob(el);
// ... The blob can then be used for uploading or other operations
## Core API of snapDOM
The core of snapDOM is the snapdom(el, options?)
function, which returns an object containing various export methods.
### Return Value of the Core Function
Calling await snapdom(element, options)
will give you an object that contains the following methods:
-
url
: (string) The Data URL of the generated SVG image. -
toRaw()
: (string) Returns the raw SVG string. -
toImg()
: (Promise) Returns an<img>
element loaded with the SVG. -
toCanvas()
: (Promise) Returns an<canvas>
element with the image drawn on it. -
toBlob(options?)
: (Promise) Returns aBlob
object containing the image data. By default, it’s in SVG format. -
toPng(options?)
: (Promise) Returns an<img>
element containing the PNG image. -
toJpg(options?)
: (Promise) Returns an<img>
element containing the JPG image. -
toWebp(options?)
: (Promise) Returns an<img>
element containing the WebP image. -
download(options?)
: (Promise) Triggers the browser to download the generated image file.
### Shortcut Methods
For convenience, snapDOM also mounts a series of static methods directly on the snapdom
object. These methods accept the element and options as arguments directly:
### Configuration Options (Options)
snapDOM provides rich configuration options, allowing you to finely control the capture and export process. All capture methods (both the core function and shortcut methods) accept an options
object as the second parameter.
### Setting Custom Dimensions (width
and height
)
Using the width
and height
options allows you to generate images with specific dimensions.
-
Fixed Width (Proportional Height)
Sets a specific width while the height adjusts automatically according to the original element’s aspect ratio.const result = await snapdom(element, { width: 400 // Outputs a 400px-wide image with auto-scaled height });
-
Fixed Height (Proportional Width)
Sets a specific height while the width adjusts automatically according to the original element’s aspect ratio.const result = await snapdom(element, { height: 200 // Outputs a 200px-tall image with auto-scaled width });
-
Fixed Width and Height (May Distort Image)
Forces the image to stretch to the specified dimensions. If the ratio differs from the original element, it may distort the image.const result = await snapdom(element, { width: 800, height: 200 // Outputs an 800px × 200px image (may stretch/squish content) });
Important Note: If the
scale
option is not1
, it takes priority overwidth
andheight
. For example,{ scale: 3, width: 500 }
will ignorewidth
and scale the image 3x instead.
### Handling Cross-Origin Images (Cross-Origin Images)
When an element contains images from other domains, the browser’s security policy (CORS) might prevent snapDOM from loading these images. snapDOM attempts by default to load images using crossOrigin="anonymous"
or crossOrigin="use-credentials"
. If loading fails, you can use the useProxy
option to specify a proxy server to resolve this issue.
const result = await snapdom(element, {
// Example proxy server (please replace with your own or a reliable public proxy)
useProxy: 'https://corsproxy.io/?url='
// Or: useProxy: 'https://api.allorigins.win/raw?url='
});
### Download Options (Download Options)
The download
method (and the snapdom.download
shortcut method) accepts a configuration object to control the download behavior:
{
format?: "svg" | "png" | "jpg" | "jpeg" | "webp"; // default: "png"
filename?: string; // default: "capture"
backgroundColor?: string; // optional override
}
For example:
await captureResult.download({
format: 'webp',
filename: 'screenshot',
backgroundColor: '#f0f0f0'
});
### Optional Helper Function: preCache()
For complex elements containing a large number of external resources (such as images and fonts), the preCache()
function can preload these resources before the actual capture, thereby improving the speed and success rate of the capture.
import { preCache } from '@zumer/snapdom';
// Preload resources for the entire page before capturing
await preCache(document.body);
// Or preload after the page has loaded
import { snapdom, preCache } from './snapdom.mjs';
window.addEventListener('load', async () => {
await preCache();
console.log('📦 Resources preloaded');
});
Options for preCache()
:
-
embedFonts
(boolean, default:true
): Whether to inline non-icon fonts during preloading. -
reset
(boolean, default:false
): Whether to clear all existing internal caches. -
useProxy
(string): Proxy server address for handling CORS images.
## Core Features and Capabilities of snapDOM
snapDOM is powerful because it supports many key modern web features:
-
Capturing Shadow DOM and Web Components: Modern frontend frameworks widely use Shadow DOM to encapsulate component styles and structure. snapDOM can delve into it and accurately capture its content. -
Support for Pseudo-elements: Pseudo-elements like ::before
,::after
, and::first-letter
are often used to add decorative content. snapDOM ensures they are correctly included in the image. -
Inlining Background Images and Fonts: To ensure the independence and portability of the image, snapDOM inlines the background images and fonts (including icon fonts like Font Awesome, Material Icons) used by the element into the generated SVG. -
Element Exclusion and Placeholders: -
You can tell snapDOM to ignore an element by adding the data-capture="exclude"
attribute to it. -
For elements containing sensitive information, you can use data-capture="placeholder"
along withdata-placeholder-text="Replacement Text"
to replace its content with specified text, achieving a masking effect.
-
## Limitations and Considerations
Despite its powerful features, there are a few points to keep in mind when using snapDOM:
-
CORS Issues with External Images: As mentioned earlier, cross-origin images require proper CORS configuration or the use of a proxy. -
Iframes are Not Supported: For security and complexity reasons, snapDOM cannot capture the content inside an <iframe>
. -
Safari Support for WebP: When using the WebP format in Safari browsers, snapDOM will automatically fall back to rendering in PNG format. -
@font-face
andFontFace()
: snapDOM has good support for the CSS@font-face
rule. However, if you use theFontFace()
API in JavaScript to dynamically load fonts, you might need to refer to the workaround mentioned in issue #43.
## Performance Benchmarks
snapDOM has undergone significant performance optimizations, especially since version v1.8.0
, with a notable performance boost.
Comparison with Simple Elements
Comparison with Complex Elements
Summary
-
The current version of snapDOM is 2 to 6 times faster than v1.8.0
. -
It’s up to 150 times faster than html2canvas
. -
It’s up to 8 times faster than html-to-image
in large scenarios.
(Benchmarks run in Chromium using Vitest. Hardware: MacBook Air 2018. Actual performance may vary depending on the device and browser.)
If you’d like to verify these performance data yourself, you can clone the snapDOM code repository and run the benchmarks:
git clone https://github.com/zumerlab/snapdom.git
cd snapdom
npm install
npm run test:benchmark
## Development and Contribution
snapDOM is an open-source project, and developers are welcome to contribute. If you want to delve into its internal implementation or contribute code, you can follow these steps for local development:
-
Clone the repository: git clone https://github.com/zumerlab/snapdom.git
-
Switch to the development branch: git checkout dev
-
Install dependencies: npm install
-
Compile the library: npm run compile
(Generates ESM, CJS, and minified versions to thedist/
directory) -
Install test browsers: npx playwright install
(Required for running tests) -
Run tests: npm test
-
Run benchmarks: npm run test:benchmark
The source code is located in the src/
directory. Detailed contribution guidelines can be found in CONTRIBUTING.md.
## Conclusion
snapDOM is a powerful, fast, and easy-to-use DOM-to-image conversion tool. Thanks to its deep support for modern web standards, outstanding performance, and flexible API, it has become a very valuable addition to a frontend developer’s toolkit. Whether you need to add screenshot functionality to your application or automate the generation of high-quality documentation images, snapDOM can provide a reliable and efficient solution.
