
It can be useful when you need to generate image previews of UI components, create visual regression tests, build user feedback tools where users screenshot parts of the page, or dynamically generate images from HTML templates on the client side.
Features:
- Full DOM Capture: Grabs everything, including nested content and Shadow DOM.
- Style Preservation: Accurately embeds computed styles, pseudo-elements (
::before,::after), and applied fonts. - Multiple Export Formats: Output as SVG Data URL,
HTMLImageElement(SVG source),HTMLCanvasElement, PNG, JPG, WebP, or SVGBlob. - Blazing Fast: Up to 148× faster than alternatives for large captures.
- Zero Dependencies: Vanilla JS, relying only on standard browser APIs.
- Exclusion/Placeholder: Options to skip elements (
data-capture="exclude") or replace them with text (data-capture="placeholder").
See It In Action:
How to use it:
1. Install snapDOM and import it into your project.
# Yarn $ yarn add @zumer/snapdom # NPM $ npm install @zumer/snapdom
import { snapdom } from '@zumer/snapdom';
// or for specific methods
import { toPng, toCanvas } from '@zumer/snapdom';2. You can also directly import the library into your HTML document:
<!-- Global object 'snapdom' -->
<script src="https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.min.js"></script>
<!-- Or as ES Module -->
<script type="module">
import { snapdom } from 'https://unpkg.com/@zumer/snapdom@latest/dist/snapdom.mjs';
window.snapdom = snapdom;
</script>3. Capture an element as an SVG Data URL.
async function captureElement(selector) {
const targetElement = document.querySelector(selector);
if (!targetElement) return;
try {
// Default capture is SVG Data URL
const svgDataUrl = await snapdom(targetElement);
// You can directly use this in an img src
const img = new Image();
img.src = svgDataUrl;
img.style.border = '1px solid #ccc'; // Add border for visibility
document.body.appendChild(img);
console.log('SVG Data URL:', svgDataUrl.substring(0, 100) + '...'); // Log prefix
} catch (error) {
console.error('snapDOM capture failed:', error);
}
}
// Example: Capture an element with id="user-card"
captureElement('#user-card');4. Available API methods. All methods take the target Element as the first argument and an optional options object as the second. They all return a Promise.
snapdom(el, options?): Returns SVG Data URL (string). The default and often most useful for sharp, scalable output.snapdom.toSvg(el, options?): Returns an SVGHTMLImageElementwith the SVG Data URL as itssrc. Convenient for immediate display.snapdom.toCanvas(el, options?): Returns anHTMLCanvasElement. Useful if you need to further manipulate the image pixel data.snapdom.toPng(el, options?): Returns anHTMLImageElementwith a PNG Data URLsrc.snapdom.toJpg(el, options?): Returns anHTMLImageElementwith a JPG Data URLsrc. Usequalityoption here.snapdom.toWebp(el, options?): Returns anHTMLImageElementwith a WebP Data URLsrc. UsequalityandbackgroundColoroptions.snapdom.toBlob(el, options?): Returns an SVGBlob. Good for sending to servers or using withURL.createObjectURL.snapdom.download(el, options?): Triggers a download.preCache(root?, options?): Preload resources for faster and more accurate captures
5. Available options.
fast: (boolean, default:true) Skips small idle delays to get results faster.embedFonts: (boolean, default:false) Inlines all non-icon fonts. Note that icon fonts are always inlined.localFonts: (array, default:[]) Specifies local fonts to be used, with each font defined as an object containing{ family, src, weight?, style? }.iconFonts: (string|RegExp|Array, default:[]) Provides extra matchers for identifying icon fonts.excludeFonts: (object, default:{}) Excludes specified font families, domains, or subsets from being embedded.scale: (number, default:1) Sets a multiplier for the output scale.dpr: (number, default:devicePixelRatio) Defines the device pixel ratio.width: (number) Sets the output width.height: (number) Sets the output height.backgroundColor: (string, default:"#fff") Provides a fallback background color for JPG and WebP image formats.quality: (number, default:1) Determines the quality for JPG or WebP images, ranging from 0 to 1.useProxy: (string, default:'') Specifies a proxy base to be used for CORS fallbacks.type: (string, default:svg) Sets the default Blob type, which can besvg,png,jpg, orwebp.exclude: (string[]) A list of CSS selectors for elements that should be excluded.excludeMode: ("hide"|"remove", default:"hide") Determines how the elements specified inexcludeare handled.filter: (function) A custom function that returns a boolean to filter elements.filterMode: ("hide"|"remove", default:"hide") Determines how the elements filtered by thefilterfunction are handled.cache: (string, default:"soft") Sets the caching behavior, with possible values beingdisabled,soft,auto, orfull.placeholders: (boolean, default:true) Shows placeholders for images and CORS iframes.fallbackURL: (string | function) Provides a fallback image to use if an<img>element fails to load.straighten: (boolean, default:false) Removestranslateandrotatetransformations from the root element while preservingscaleandskew, creating a flat capture.noShadows: (boolean, default:false) Prevents the expansion of the root’s bounding box for effects like shadows, blur, and outlines, and removes these effects from the cloned root.
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";
}
});Best Practices & Performance:
Font Loading: snapDOM automatically waits for document.fonts.ready. Ensure your fonts are loaded before initiating the capture if you rely on custom web fonts. If fonts load after the capture starts, they might not render correctly.
CORS: External images (e.g., <img> tags with src pointing to another domain) must be served with permissive CORS headers (Access-Control-Allow-Origin). The browser’s security rules prevent canvas/SVG tainting otherwise. snapDOM tries to fetch and inline these as Data URLs. If it fails due to CORS, the image might be missing.
Complexity: While fast, capturing extremely large or complex DOM trees (thousands of nodes deep) will naturally take longer. Consider capturing smaller, more targeted elements if performance is critical on massive pages.
SVG vs. Raster: SVG output is generally preferred for fidelity and scalability. Use PNG/JPG/WebP mainly when you need a specific raster format or transparency isn’t desired (JPG). SVG captures can sometimes result in larger file sizes if they contain many embedded raster images.
Compared to Alternatives
| Library | Speed (ms) | SVG Output | Shadow DOM | Pseudo-Elements |
|---|---|---|---|---|
| snapDOM | 12 | ✅ | ✅ | ✅ |
| html2canvas | 650 | ❌ | ❌ | Partial |
| dom-to-image | 320 | ✅ | ❌ | ❌ |
| modern-screenshot | 110 | ❌ | ✅ | ❌ |
FAQs
Q: Why are images from another domain not showing up?
A: This is almost certainly a CORS issue. The server hosting the external image needs to send Access-Control-Allow-Origin headers that permit your site to fetch the image data. Without it, the browser blocks access, and snapDOM can’t inline the image. Check your browser’s console for CORS errors.
Q: My custom web fonts look wrong in the capture.
A: Make sure the font is fully loaded before you call snapdom. snapDOM waits for document.fonts.ready, but if you trigger the capture during font loading, it might capture before the font is applied. Use CSS font-display: block; initially or explicitly await your font loading promises if needed.
Q: Can it capture content inside an <iframe>?
A: No, snapDOM doesn’t capture iframe content due to browser security restrictions (cross-origin limitations). It captures the <iframe> element itself, but not its internal document.
Q: How does scaling work? Does scale: 2 make it twice as slow?
A: The scale option increases the dimensions of the output SVG/Canvas. It might increase processing time slightly, but usually not dramatically like 2x slower. It’s useful for getting higher-resolution PNG/JPG outputs from the intermediate canvas stage. For SVG, it mainly affects the viewBox and width/height attributes.
Q: What’s the difference between snapdom() and snapdom.toImg()?
snapdom() returns a Promise<string> containing the SVG Data URL. snapdom.toImg() returns a Promise<HTMLImageElement> where the src attribute is set to that SVG Data URL. toImg is just a convenience wrapper if you immediately want an <img> tag.
Q: Is there a size limit to what it can capture?
A: There’s no hardcoded limit, but extremely large and complex DOM structures will consume more memory and CPU during capture. Browser limitations on memory or rendering extremely large SVGs/Canvases could theoretically be hit in extreme edge cases, but for typical web pages and components, it should be fine. The performance benchmarks show it handles very large dimensions well compared to others.
Changelog:
v2.1.0 (03/10/2026)
- fix: use nodeMap for source-clone alignment in inlinePseudoElements
- Update URL handling to use location.origin in fonts.js
- fix(background): inline background-image inside shadow DOM hosts
- feat: classify open issues by importance with priority labels and automated triage
- fix: CSS transform double scale bug
- fix: dynamic injected stylesheets with fonts
- Fix: Inherit root font-size in SVG output
v2.0.2 (01/28/2026)
- bugfix
v2.0.1 (11/26/2025)
- bugfix
v2.0.0 (11/19/2025)
- fix: improve CSS src property parsing in font faces
- Fix placeholder dimensions when image loading fails
v1.9.13 (10/05/2025)
- Adding ‘exclusionMode’ option
- Refactor: use BlobType alias consistently
- Improve CSS vars detection
- Fix toImg() dimensions when scale==1
- Enhance web fonts detection on deph relative paths
- Add two new options to control transforms and shadows on root element
- Add toSvg() in replacement of toImg()
- Improve relative path detection
v1.9.11 (09/10/2025)
- Fix Safari bug that prevents capture
v1.9.10 (08/14/2025)
- feat: fast configuration item to control deep recursion of deepClone
- Fix the issue when image loading fails and add a default image placeholder attribute
v1.9.9 (08/14/2025)
- Improves external fonts handling.
- Handles srcset.
- Fix speed regression.
- Handles Blob src.
v1.9.8 (08/09/2025)
- fix: invalid border-width check
- fix(types): update preCache
v1.9.7 (07/27/2025)
- Improve pseudo elements detection.
- Remove default backgroundColor on download().
- Bugfixes
v1.9.6 (07/20/2025)
- Add options argument to toBlob function
- Keep canvas CSS style
- Improve: handles local() source font
- Improve webcomponent clone
- Perf: unifies cache
- Improve cache handling
- Adjust cache reset
- Improve regex
- Add primitive support to css counter
- Fix bug background-color on export formats
- Fix regression textArea duplication
- Prevent process local ids
v1.9.5 (07/14/2025)
- copy checkbox.indeterminate
- update docs to show exclude and filter
- fix: add type def for SnapOptions
- dd slot detection and Fix textarea content duplication
v1.9.3 (07/10/2025)
- Add filter and exclude options for element exclusion.
- Missing width and height in types.
- fix: type check.
- Core update: Capture speed is drammatically increased.
- Core update: tries differents methods to fetch image, even proxy for CORS denied images. Important: crossOrigin is now inbuilt into fetchImages(), no longer needed as option.
- Improve fetchImage() by skiping svg format.
- Add iconFont options and fix doubled icon render.
- Add Layui icon font.
- Add Blob Types.
- Bug: fixes hidden last line PRE tag.
- Feat: handles external SVG defs.
- Prevents double url encoding.
- Fix scale background-image
v1.8.1 (06/30/2025)
- Add Lucide to icon font detection
- Fix: encode same uri multiple times
- Avoid background-image logic duplication
- Improve split multiple backgrounds
- Fix background image handling
- Feat: sanitize rootElement to avoid CSS layout conflicts
- Clean transform RootElement prop
- Fix: canvas style props
- Feat: handling @import and optimice cache
- Compile .js to es2015
- Improve inlinePseudoElements() to handle decorative properties
- Add ::first-letter detection
v1.7.0 (06/19/2025)
- add options.crossOrigin
- Improve inlineBackgroundImages to support multiple background-image values
v1.3.0 (06/14/2025)
- Fix: double scaled images
- Fix: background img & img base64 in pseudo elements
- Feat: captures input values
- Improve: Device Pixel Ratio handling
v1.2.5 (06/09/2025)
- Bugfixes
v1.2.2 (06/04/2025)
- Patch: type script definitions
v1.2.1 (05/31/2025)
- Feat(embedFonts): also embed icon fonts when embedFonts is true
- Fix expose snapdom and preCache on browser compilation
- Improve icon-font conversion
- Fix compress mode
v1.1.0 (05/28/2025)
- Add typescript declaration
- Feat. support scrolling state
- Fix bug by removing trim spaces
- Fix bug that prevents scale on png format
v1.0.0 (05/19/2025)
- Fix retina and scale bug
- Improve public API
- Fix bug to render canvas with precache compress mode
- Update to reflect new public API
- Add helper to check Safari
v0.9.9 (05/16/2025)
- Fix bug on collectUsedTagNames()
v0.9.8 (05/14/2025)
- Fix a bug in capture output format
v0.9.7 (05/14/2025)
- Add an option to switch between smooth and fast capture
- Improve detection of browsers default css styles
- Size of generated image is smaller in compress mode
- Enable embedding fonts
- Enable a pre caching for static assets (WIP)
The post snapDOM: Fast & Accurate DOM to Image Capture Library appeared first on CSS Script.
Discover more from RSS Feeds Cloud
Subscribe to get the latest posts sent to your email.
