dom-to-image-more

Turn any DOM node into a PNG, JPEG, SVG, or canvas image entirely in the browser, no server or screenshot service required.

Library
npm
v3.10.2
680stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
81/100Excellent
Development Activity84
Maintenance84
Community68
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture72
Code Quality78
Innovation62
Learning Curve80

dom-to-image-more is a browser library that renders an arbitrary DOM node (including same-origin and blob iframes) into a raster (PNG/JPEG) or vector (SVG) image using an SVG foreignObject and HTML5 canvas, all client-side with no server round trip. It is a long-running, actively maintained fork of Anatolii Saienko’s original dom-to-image (itself built on Paul Bakaus’s domvas), carrying forward the original approach while fixing a long list of fidelity bugs and adding features the original never gained.

The library walks and deep-clones the target node, inlines every external dependency the clone needs to render standalone — images, @font-face web fonts, CSS background/mask URLs, and nested SVG <use>/<image> references — then serializes the clone into an SVG data URI and draws it to a canvas. A requestInterceptor hook unifies that whole resource-fetching path, letting callers supply or recover any external resource before or after a fetch attempt, with per-resource-type fallbacks instead of one global placeholder.

Beyond the resource pipeline, it exposes fine-grained rendering controls: adjustClonedNode and onclone hooks for mutating the clone before capture, adjustPseudoElement for editing or dropping ::before/::after content, pixelRatio for high-DPI output, preserveScroll to keep nested scroll positions instead of resetting them, and filterUrls/filterStyles for selectively excluding resources or CSS properties from the output. It ships a bundled TypeScript definition file and is validated against real Chrome and Firefox via Karma, plus a dedicated SSR smoke test and tsc-based type tests.

What You Get

  • toPng/toJpeg/toSvg/toCanvas/toBlob/toPixelData — six output functions covering raster, vector, canvas, blob, and raw-pixel capture, all returning promises
  • requestInterceptor — a single hook to supply or recover any external image/font/stylesheet resource, consulted both before the fetch and on failure
  • Web font and image inlining — discovers @font-face rules (including in cross-origin stylesheets via opt-in loadExternalStyleSheet) and inlines fonts and images as data URIs so the output is self-contained
  • Clone-time hooksadjustClonedNode, onclone, and adjustPseudoElement for mutating or filtering the cloned tree, including dropping or rewriting ::before/::after content
  • High-DPI and scroll fidelitypixelRatio for crisp Retina output and preserveScroll to reflect each element’s actual scroll position instead of resetting it
  • Bundled TypeScript definitions — a hand-maintained .d.ts validated by its own tsc --strict type-test suite

Common Use Cases

  • Exporting a chart, dashboard widget, or report section as a downloadable PNG/JPEG image
  • Generating a shareable image snapshot of user-generated content (e.g. a card, invoice, or certificate) without a server-side screenshot pipeline
  • Capturing SVG output of arbitrary HTML for further vector editing or embedding
  • Building client-side ‘export as image’ or ‘copy as image’ features in web apps that must work entirely offline/client-side

Under The Hood

Architecture The entire library lives in a single file (src/dom-to-image-more.js) organized as a set of factory functions — newUtil, newInliner, newFontFaces, newImages — each returning a closures-based object exposing a narrow set of methods, invoked once at module load to build shared singleton helpers (util, inliner, fontFaces, images) used throughout the six public entry points (toSvg, toPng, toJpeg, toBlob, toCanvas, toPixelData). The render pipeline is linear and easy to trace: draw() clones the target node via cloneNode() (which recursively walks children, computed styles, and pseudo-elements), embedFonts()/inlineImages() replace every external reference with inlined data URIs through the requestInterceptor hook, the result is serialized to an SVG data URI, and that SVG is drawn to a canvas sized and scaled per pixelRatio. Nothing in the core pipeline can be swapped without editing the file directly — there’s no plugin registry — but the hook surface (adjustClonedNode, onclone, adjustPseudoElement, filterUrls, filterStyles, requestInterceptor) gives callers well-defined seams into each stage without needing to fork the core traversal.

Tech Stack The library has zero runtime dependencies and targets the browser DOM/Canvas/SVG APIs directly with no framework. It ships as a UMD bundle (dist/dom-to-image-more.min.js, built via Grunt/grunt-contrib-uglify) alongside a hand-maintained dom-to-image-more.d.ts for TypeScript consumers. Development tooling is ESLint (flat config, eslint:recommended plus a no-unused-vars rule set) and Prettier for formatting, Karma with the Mocha/Chai/karma-chrome-launcher/karma-firefox-launcher stack for real-browser test execution, and a small Node-based SSR smoke test to catch server-side-rendering breakage. TypeScript itself is used only as a devDependency to type-check the bundled .d.ts against a dedicated test-definitions file.

Code Quality Testing is extensive relative to the library’s size: a single ~4,000-line Karma/Mocha/Chai spec (spec/dom-to-image-more.spec.js) exercises the rendering pipeline against dozens of fixture pages under spec/resources/ (fonts, iframes, shadow DOM, SVG namespaces, scrolling, pseudo-elements, and more), run against actual Chrome and Firefox rather than a DOM-emulation layer. A separate test-node/ssr-smoke.js verifies the library fails cleanly under Node/SSR instead of throwing a raw ReferenceError, and test-d/dom-to-image-more.test-d.ts type-checks the public API surface via tsc --strict. Error handling favors graceful degradation over throwing — failed resource fetches resolve to an empty string or a placeholder rather than rejecting the whole render — and diagnostics are routed through a replaceable logger option instead of hardcoded console calls. The single large source file and use of var/closures rather than ES classes or modules is dated by modern standards, but naming is consistent and the flat-config ESLint plus Prettier setup is actively enforced in CI (lint script, --max-warnings=0).

What Makes It Unique Unlike libraries that rasterize by walking layout boxes or driving a headless browser, dom-to-image-more’s SVG-foreignObject approach lets the browser’s own layout and paint engine render the cloned DOM tree, which is what gives it fidelity for CSS features (masks, pseudo-elements, web fonts, nested SVG) that box-model reimplementations tend to miss. Its most distinctive addition versus the upstream project it forked from is the unified requestInterceptor hook, which collapses what used to be separate ad hoc image/font-fetching code paths into one consistently-applied interception point with per-resource-type fallback behavior — giving callers a single place to add proxying, caching, or CORS workarounds instead of patching multiple internal fetch call sites.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search