Categories: CSSScriptWeb Design

snapDOM: Fast & Accurate DOM to Image Capture Library

snapDOM is a JavaScript-driven DOM capture tool that converts any HTML element into a scalable SVG image.

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 SVG Blob.
  • 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 SVG HTMLImageElement with the SVG Data URL as its src. Convenient for immediate display.
  • snapdom.toCanvas(el, options?): Returns an HTMLCanvasElement. Useful if you need to further manipulate the image pixel data.
  • snapdom.toPng(el, options?): Returns an HTMLImageElement with a PNG Data URL src.
  • snapdom.toJpg(el, options?): Returns an HTMLImageElement with a JPG Data URL src. Use quality option here.
  • snapdom.toWebp(el, options?): Returns an HTMLImageElement with a WebP Data URL src. Use quality and backgroundColor options.
  • snapdom.toBlob(el, options?): Returns an SVG Blob. Good for sending to servers or using with URL.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 be svg, png, jpg, or webp.
  • exclude: (string[]) A list of CSS selectors for elements that should be excluded.
  • excludeMode: ("hide"|"remove", default: "hide") Determines how the elements specified in exclude are handled.
  • filter: (function) A custom function that returns a boolean to filter elements.
  • filterMode: ("hide"|"remove", default: "hide") Determines how the elements filtered by the filter function are handled.
  • cache: (string, default: "soft") Sets the caching behavior, with possible values being disabled, soft, auto, or full.
  • 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) Removes translate and rotate transformations from the root element while preserving scale and skew, 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.

rssfeeds-admin

Share
Published by
rssfeeds-admin

Recent Posts

Watch the First Clips From Tomorrow’s Spider-Man: Brand New Day Trailer Here Now, With More Set to Be Released Throughout Today

The first full trailer for Spider-Man: Brand New Day will be released tomorrow — but…

23 minutes ago

Buffy the Vampire Slayer Star Reveals Reason Reboot Was Canceled, Slams Timing and Blames 1 Executive Who Was ‘Not a Fan of The Original’

Sarah Michelle Gellar has discussed the shock cancellation of her Buffy the Vampire Slayer reboot…

24 minutes ago

Saudi Arabia Fund Acquires Another Slice of Resident Evil Requiem Publisher Capcom, Upping Country’s Ownership to 10%

Saudi Arabia now owns 10% of Capcom, after Saudi Crown Prince Mohammed Bin Salman's Electronic…

24 minutes ago

Wired’s New Editor Doesn’t Care If The Tech Bros Are Mad

The post Wired’s New Editor Doesn’t Care If The Tech Bros Are Mad appeared first…

33 minutes ago

2026 NAB Show Offering Free Show Floor Passes To Creators

The post 2026 NAB Show Offering Free Show Floor Passes To Creators appeared first on…

33 minutes ago

Spectrum Launches Multiview For NCAA Basketball Tournaments

Today, Spectrum launched its new Multiview feature in the Spectrum TV App, giving customers the ability to…

33 minutes ago

This website uses cookies.