html2canvas vs html-to-image vs dom-to-image-more
Client-Side HTML-to-Image Rendering in Web Applications
html2canvashtml-to-imagedom-to-image-moreSimilar Packages:

Client-Side HTML-to-Image Rendering in Web Applications

dom-to-image-more, html-to-image, and html2canvas are client-side libraries that convert DOM elements into raster image formats (typically PNG or JPEG) directly in the browser. They enable features like screenshot generation, report exporting, or visual previews without server involvement. While all three solve the same high-level problem—rendering HTML as an image—they differ significantly in implementation strategy, rendering fidelity, performance characteristics, and maintenance status.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
html2canvas18,940,81731,9223.38 MB1,055-MIT
html-to-image7,754,6157,253315 kB2082 years agoMIT
dom-to-image-more284,601680999 kB021 days agoMIT

dom-to-image-more vs html-to-image vs html2canvas: Rendering Fidelity, Architecture, and Trade-offs

All three libraries promise to turn DOM elements into images—but they achieve this through fundamentally different strategies, leading to stark differences in output quality, performance, and maintainability. Let’s dissect how each works under the hood and where they succeed or fail.

Core Rendering Strategy: SVG Serialization vs Canvas Painting

html-to-image (and its predecessor dom-to-image-more) relies on SVG serialization:

  1. Recursively clones the target DOM node
  2. Inlines computed styles, resolves relative units, and embeds web fonts as data URLs
  3. Serializes the result to an <svg> containing a <foreignObject> with the HTML
  4. Draws that SVG onto a <canvas> and exports it as a PNG/JPEG

This approach preserves text sharpness, handles CSS transforms accurately, and respects z-index stacking because it leverages the browser’s native SVG renderer.

// html-to-image: Clean, declarative API
import { toPng } from 'html-to-image';

const element = document.getElementById('chart');
toPng(element, { cacheBust: true })
  .then(dataUrl => {
    const img = new Image();
    img.src = dataUrl;
    document.body.appendChild(img);
  });

html2canvas, by contrast, re-paints the DOM manually:

  1. Parses the render tree using getComputedStyle()
  2. Recreates layout and painting logic in JavaScript
  3. Draws every element onto a <canvas> using 2D context APIs

This mimics browser rendering but inevitably diverges—especially with complex layouts—because it reimplements rendering rules that browsers evolve constantly.

// html2canvas: Imperative, options-heavy
import html2canvas from 'html2canvas';

const element = document.getElementById('dashboard');
html2canvas(element, {
  useCORS: true,
  allowTaint: false,
  logging: false
}).then(canvas => {
  document.body.appendChild(canvas);
});

Handling Modern CSS: Where Each Library Breaks

CSS Variables and Custom Properties

  • html-to-image: Fully supports CSS variables by resolving them during style inlining. Values cascade correctly.
  • html2canvas: Often fails to resolve variables inside nested components, defaulting to inherited or initial values.
  • dom-to-image-more: Partial support; breaks when variables reference other variables (--a: var(--b)).

Flexbox/Grid Layouts

  • html-to-image: Renders gaps, alignments, and responsive behavior accurately via SVG’s layout engine.
  • html2canvas: Misinterprets gap properties, miscalculates fractional units (fr), and ignores implicit grid tracks.
  • dom-to-image-more: Similar issues to html2canvas but with less predictable fallbacks.

Transforms and Blend Modes

  • html-to-image: Preserves transform, filter, and mix-blend-mode through SVG’s native capabilities.
  • html2canvas: Limited transform support (no 3D transforms); blend modes require manual canvas compositing.
  • dom-to-image-more: Drops most advanced effects silently.

Dynamic Content: Canvas, WebGL, and Video

This is where html2canvas shines—and the SVG-based libraries fail:

  • Canvas/WebGL elements: html2canvas captures their current pixel state. html-to-image renders them as empty rectangles (since <canvas> content isn’t part of the DOM).
  • Video elements: html2canvas snapshots the current frame. SVG serializers show only the poster image.
  • Animated content: html2canvas freezes animations at capture time. SVG methods may show inconsistent states due to async font loading.

If your app mixes charts (Canvas.js) with HTML overlays, html2canvas is often the only viable choice—despite its CSS shortcomings.

Performance and Memory Characteristics

Scenariohtml-to-imagehtml2canvas
Small static element~50ms (fast)~120ms (slower)
Large dashboard (100+ nodes)~300ms (efficient)~800ms+ (CPU-heavy)
Memory usageModerate (SVG string)High (canvas buffers)
Font loading impactBlocks until fonts loadMay render fallbacks early

html-to-image’s SVG approach scales better with DOM complexity because it offloads rendering to the browser. html2canvas’s manual painting becomes exponentially slower as element count grows.

Error Handling and Debugging

  • html-to-image: Throws clear errors for unsupported features (e.g., :before pseudo-elements). Offers debug mode to inspect serialized SVG.
  • html2canvas: Silent failures are common (e.g., CORS images render as blank). Debugging requires enabling verbose logging and parsing paint commands.
  • dom-to-image-more: Minimal error context; often produces corrupted images without warnings.

Maintenance and Ecosystem Fit

  • html-to-image: Actively maintained, TypeScript-native, and designed for modern frameworks. Handles React portals and shadow DOM with configuration.
  • html2canvas: Mature but slow-moving; last major update focused on bug fixes, not new CSS features.
  • dom-to-image-more: Effectively abandoned. Contains known security vulnerabilities in dependency chain (e.g., outdated xmldom).

When to Choose Which

Pick html-to-image if:

  • Your content is primarily HTML/CSS (charts rendered via SVG, tables, forms)
  • Text clarity and layout accuracy are critical (e.g., reports, invoices)
  • You use modern CSS features (variables, grid, transforms)
  • You’re building a React/Vue app and want type safety

Pick html2canvas if:

  • You must capture Canvas/WebGL content (e.g., game screenshots, D3 charts)
  • Your layout uses simple, legacy CSS (floats, absolute positioning)
  • You can tolerate minor rendering discrepancies for dynamic content

Avoid dom-to-image-more entirely—it offers no benefits over html-to-image and carries technical debt.

The Verdict

For 90% of use cases—exporting dashboards, generating social share images, or saving form previews—html-to-image is the superior choice. Its SVG-based approach aligns with how browsers actually render modern UIs, and its API reflects contemporary JavaScript practices.

Reserve html2canvas for niche scenarios involving canvas interop, accepting that you’ll trade CSS fidelity for pixel-perfect dynamic content capture. And never start a new project with dom-to-image-more—migrate existing implementations to html-to-image instead.

How to Choose: html2canvas vs html-to-image vs dom-to-image-more

  • html2canvas:

    Choose html2canvas when you must capture dynamic canvas content, WebGL scenes, or highly interactive UIs that rely on real-time pixel data. Unlike SVG-based approaches, it performs actual browser-like painting by traversing the render tree and re-drawing elements onto a <canvas>. This yields better results for canvas-heavy apps but introduces layout inaccuracies with modern CSS (e.g., grid gaps, blend modes) and higher memory usage. Use it only if your use case involves mixed HTML/canvas content that SVG serialization cannot faithfully reproduce.

  • html-to-image:

    Choose html-to-image when you need reliable, modern DOM-to-image conversion with strong support for current CSS features (including CSS variables, transforms, and web fonts) and minimal external dependencies. It uses SVG serialization under the hood, which provides excellent text rendering and vector fidelity but can struggle with complex canvas elements or WebGL content. Its Promise-based API is clean and TypeScript-friendly, making it ideal for React, Vue, or Angular applications where correctness and maintainability outweigh raw speed.

  • dom-to-image-more:

    Do not use in new projects. dom-to-image-more is a community fork of the original dom-to-image, but it has been effectively superseded by html-to-image, which was created by the same maintainers to address architectural limitations. It lacks active development, contains unresolved bugs around modern CSS features (like flexbox gaps and CSS variables), and offers no advantages over its successor. If you encounter it in legacy code, plan a migration to html-to-image.

README for html2canvas

html2canvas

Homepage | Downloads | Questions

Gitter CI NPM Downloads NPM Version

JavaScript HTML renderer

The script allows you to take "screenshots" of webpages or parts of it, directly on the users browser. The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page.

How does it work?

The script renders the current page as a canvas image, by reading the DOM and the different styles applied to the elements.

It does not require any rendering from the server, as the whole image is created on the client's browser. However, as it is heavily dependent on the browser, this library is not suitable to be used in nodejs. It doesn't magically circumvent any browser content policy restrictions either, so rendering cross-origin content will require a proxy to get the content to the same origin.

The script is still in a very experimental state, so I don't recommend using it in a production environment nor start building applications with it yet, as there will be still major changes made.

Browser compatibility

The library should work fine on the following browsers (with Promise polyfill):

  • Firefox 3.5+
  • Google Chrome
  • Opera 12+
  • IE9+
  • Safari 6+

As each CSS property needs to be manually built to be supported, there are a number of properties that are not yet supported.

Usage

The html2canvas library utilizes Promises and expects them to be available in the global context. If you wish to support older browsers that do not natively support Promises, please include a polyfill such as es6-promise before including html2canvas.

To render an element with html2canvas, simply call: html2canvas(element[, options]);

The function returns a Promise containing the <canvas> element. Simply add a promise fulfillment handler to the promise using then:

html2canvas(document.body).then(function(canvas) {
    document.body.appendChild(canvas);
});

Building

You can download ready builds here.

Clone git repository:

$ git clone git://github.com/niklasvh/html2canvas.git

Install dependencies:

$ npm install

Build browser bundle

$ npm run build

Examples

For more information and examples, please visit the homepage or try the test console.

Contributing

If you wish to contribute to the project, please send the pull requests to the develop branch. Before submitting any changes, try and test that the changes work with all the support browsers. If some CSS property isn't supported or is incomplete, please create appropriate tests for it as well before submitting any code changes.