dom-to-image vs html-to-image vs html2canvas vs screenshot-desktop
Web フロントエンドにおける DOM スクリーンショット生成ライブラリの選定
dom-to-imagehtml-to-imagehtml2canvasscreenshot-desktop類似パッケージ:

Web フロントエンドにおける DOM スクリーンショット生成ライブラリの選定

dom-to-imagehtml-to-imagehtml2canvas は、ブラウザ上で DOM 要素を画像(PNG/JPEG/SVG)に変換するためのライブラリです。これらは主に、UI のスクリーンショット取得、レポート生成、SNS シェア用画像作成などのフロントエンドユースケースで使われます。一方、screenshot-desktop は Node.js 向けのデスクトップ全体のスクリーンショット取得ライブラリであり、ブラウザ環境ではなく Electron やデスクトップ自動化ツールなどで使用されます。この比較では、Web フロントエンド開発者が DOM キャプチャ機能を実装する際に適切なパッケージを選定できるよう、技術的特性と実用性に焦点を当てて解説します。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
dom-to-image010,781-3378年前MIT
html-to-image07,082315 kB1951年前MIT
html2canvas031,8253.38 MB1,048-MIT
screenshot-desktop049641.9 kB245ヶ月前MIT

Web 上の DOM スクリーンショット生成ライブラリ比較:dom-to-image、html-to-image、html2canvas、screenshot-desktop

フロントエンド開発において、DOM 要素を画像として保存・共有する必要が生じることはよくあります。例えば、レポート出力、SNS シェア用プレビュー、または UI の視覚的バグ報告などが該当します。しかし、これらの要望を実現するには複数の技術的制約(CORS、フォント、SVG、iframe など)を乗り越える必要があります。この記事では、代表的な npm パッケージである dom-to-imagehtml-to-imagehtml2canvas、および screenshot-desktop を、実際の開発現場での使用観点から深く比較します。

📸 基本的な用途と対象範囲

まず重要なのは、各パッケージが「何をキャプチャできるか」です。

dom-to-imagehtml-to-imagehtml2canvas はすべて ブラウザ上で動作し、DOM 要素を画像化することを目的としています。これらはクライアントサイド JavaScript で使われ、ユーザーの画面内の特定の HTML 要素(例: <div id="chart">)を PNG や JPEG に変換します。

一方、screenshot-desktopNode.js 向けのデスクトップ全体またはディスプレイのスクリーンショット取得ライブラリです。これはブラウザ外で動作し、Electron アプリやデスクトップ自動化ツールなどで使われます。Web ページ内の要素を撮影する用途にはまったく使えません

💡 補足:screenshot-desktop はブラウザ環境で動作しないため、通常の Web アプリ(React/Vue/Angular など)では使用できません。誤ってインストールしないよう注意が必要です。

以下では、Web フロントエンド向けの3つのライブラリ(dom-to-imagehtml-to-imagehtml2canvas)を中心に比較します。

🔧 動作原理と描画品質

html2canvas

html2canvas は、Canvas API を使って DOM を再現します。CSS プロパティを解析し、それを Canvas コンテキストに変換して描画します。この方式の利点は、iframe や外部ドメインの画像などの制限が比較的少ないことです(ただし CORS 制約は依然存在)。

ただし、完全な CSS サポートがあるわけではなく、一部のプロパティ(例: filterclip-pathtransform-style: preserve-3d)は正しく描画されないことがあります。

// html2canvas の基本的な使い方
import html2canvas from 'html2canvas';

const element = document.getElementById('capture');
html2canvas(element).then(canvas => {
  const imgData = canvas.toDataURL('image/png');
  // imgData をダウンロードまたは表示
});

dom-to-imagehtml-to-image

両者は非常に似ていますが、html-to-imagedom-to-imageフォークであり、メンテナンスが活発です。動作原理は共通で、以下のステップで画像を生成します:

  1. 対象 DOM を SVG 内に <foreignObject> として埋め込む
  2. その SVG を Data URL に変換
  3. <img> 要素で読み込み、Canvas に描画
  4. Canvas から画像データを抽出

この方式は CSS の忠実度が高い(特にフォントや装飾)ですが、CORS 制約が厳しくなります。外部ドメインの画像やフォントはブロックされる可能性があります。

// dom-to-image の使い方
import domtoimage from 'dom-to-image';

const node = document.getElementById('capture');
domtoimage.toPng(node)
  .then(dataUrl => {
    // dataUrl を使用
  });
// html-to-image の使い方(API はほぼ同じ)
import { toPng } from 'html-to-image';

const node = document.getElementById('capture');
toPng(node)
  .then(dataUrl => {
    // dataUrl を使用
  });

⚠️ 注意:dom-to-image は GitHub リポジトリが更新されておらず、npm にも「このパッケージは非推奨です。代わりに html-to-image を使ってください」という警告が記載されています。新規プロジェクトでは使用すべきではありません。

🌐 外部リソース(画像・フォント)の扱い

html2canvas

  • 外部画像:CORS 設定が適切であれば読み込み可能(useCORS: true オプション必須)
  • Web フォント:allowTaint: trueuseCORS: true を組み合わせて、ある程度対応可能
html2canvas(element, {
  useCORS: true,
  allowTaint: true
}).then(canvas => { /* ... */ });

html-to-image

  • 外部画像:CORS が有効でない場合、画像が欠落またはエラーになる
  • Web フォント:fontEmbedCssUrl オプションで CSS を埋め込むことで対応可能
import { toPng } from 'html-to-image';

toPng(node, {
  fontEmbedCssUrl: '/path/to/fonts.css'
}).then(dataUrl => { /* ... */ });

dom-to-image にも同様のオプションがありますが、メンテナンスされていないため、最新のブラウザ挙動に対応していない可能性があります。

🛠️ 機能とカスタマイズ性

機能html2canvashtml-to-imagedom-to-image
解像度スケーリング✅ (scale オプション)✅ (pixelRatio)✅ (pixelRatio)
背景指定✅ (backgroundColor)✅ (backgroundColor)✅ (bgcolor)
要素の除外✅ (ignoreElements)✅ (skipNode)✅ (filter)
SVG サポート⚠️ 限定的✅ 良好✅ 良好
ダウンロードヘルパー✅ (download 関数)

html-to-imagedownload ユーティリティ関数を提供しており、画像を直接ダウンロードさせるのが簡単です:

import { toPng, download } from 'html-to-image';

toPng(node).then(download);

一方、html2canvas は純粋に Canvas を返すだけなので、ダウンロード処理は自分で実装する必要があります。

🖥️ screenshot-desktop についての補足

screenshot-desktop は Node.js 環境専用であり、以下のような用途に使われます:

  • Electron アプリで現在のデスクトップをキャプチャ
  • 自動テスト中にスクリーンショットを取得
  • デスクトップ自動化スクリプト
// screenshot-desktop の使い方(Node.js のみ)
const screenshot = require('screenshot-desktop');

screenshot().then(img => {
  // img は Buffer(PNG データ)
  require('fs').writeFileSync('screenshot.png', img);
});

このライブラリは ブラウザで動作しないため、Web アプリの DOM キャプチャには一切使えません。混同しないよう注意してください。

📊 実用的な選択ガイド

シナリオ 1: 高忠実度の UI スクリーンショット(社内ツールなど)

  • 外部リソースが少なく、CORS 問題がない
  • フォントや装飾の再現が重要
  • 推奨: html-to-image

シナリオ 2: 外部画像や iframe を含む複雑な DOM

  • CORS 設定が可能な環境(例: 同一ドメイン or 許可済み CDN)
  • 少しの描画ずれは許容できる
  • 推奨: html2canvas

シナリオ 3: デスクトップアプリ(Electron)での全画面キャプチャ

  • ブラウザ外で動作する必要がある
  • DOM ではなく OS レベルのスクリーンショットが必要
  • 推奨: screenshot-desktop

シナリオ 4: 既存コードで dom-to-image を使っている

  • 新規開発ではないが、動作している
  • 対応: 将来的には html-to-image への移行を検討

🚫 非推奨ライブラリの明確化

公式 npm ページおよび GitHub リポジトリの情報によると:

  • dom-to-image は非推奨(deprecated) と明記されています。最後のコミットは数年前であり、バグ修正や新機能追加は行われていません。
  • 新規プロジェクトでは 絶対に使用すべきではありません

代わりに、作者が推奨している html-to-image を使用してください。これは dom-to-image の後継として開発されており、API 互換性を保ちつつ、バグ修正と改善が継続されています。

💡 最終的なまとめ

パッケージ推奨度主な用途注意点
html-to-image⭐⭐⭐⭐⭐Web フロントエンドでの高品質 DOM キャプチャCORS 制約に注意
html2canvas⭐⭐⭐⭐☆外部リソースを含む DOM キャプチャCSS 再現性に若干の限界
dom-to-image⚠️ 非推奨(新規使用不可)使用を避けてください
screenshot-desktop⭐⭐⭐⭐☆(ただし用途限定)Node.js デスクトップアプリでのスクリーンショットブラウザでは動作しない

結論として

  • Web アプリで DOM を画像化したいなら、まず html-to-image を試す
  • CORS や外部画像の問題が深刻なら html2canvas を検討する
  • dom-to-image は新規プロジェクトで使うべきではない
  • デスクトップアプリで全画面キャプチャが必要なら screenshot-desktop を使うが、Web フロントエンドとは無関係であることを理解しておくこと。

これらの選択は、単なる「どちらが人気か」ではなく、「あなたのアプリの技術的制約と要件にどれが最もフィットするか」に基づいて判断すべきです。

選び方: dom-to-image vs html-to-image vs html2canvas vs screenshot-desktop

  • dom-to-image:

    dom-to-image は非推奨(deprecated)と公式に明記されており、新規プロジェクトでの使用は避けるべきです。GitHub リポジトリの更新も長期間停止しており、バグ修正や新機能追加は行われていません。既存コードで使用されている場合は、後継の html-to-image への移行を強く推奨します。

  • html-to-image:

    html-to-imagedom-to-image のメンテナンスされたフォークであり、高忠実度の DOM キャプチャが必要な Web フロントエンドプロジェクトに最適です。CSS 装飾や Web フォントの再現性が高く、ダウンロードヘルパー関数も提供されています。ただし、CORS 制約が厳しく、外部ドメインの画像やフォントを使用する場合は事前に対策が必要です。

  • html2canvas:

    html2canvas は、外部リソース(CORS 許可済みの画像や iframe)を含む複雑な DOM をキャプチャする必要がある場合に適しています。Canvas ベースの描画方式により、一部の CSS プロパティの再現性に限界がありますが、柔軟なオプション設定と広いブラウザサポートが強みです。描画品質より可用性を重視するケースに向いています。

  • screenshot-desktop:

    screenshot-desktop は Node.js 環境専用のデスクトップスクリーンショットライブラリであり、ブラウザベースの Web アプリでは使用できません。Electron アプリやデスクトップ自動化ツールで、OS レベルの全画面または特定ディスプレイのキャプチャが必要な場合にのみ選択してください。DOM 要素の画像化とは無関係です。

dom-to-image のREADME

DOM to Image

Build Status

What is it

dom-to-image is a library which can turn arbitrary DOM node into a vector (SVG) or raster (PNG or JPEG) image, written in JavaScript. It's based on domvas by Paul Bakaus and has been completely rewritten, with some bugs fixed and some new features (like web font and image support) added.

Installation

NPM

npm install dom-to-image

Then load

/* in ES 6 */
import domtoimage from 'dom-to-image';
/* in ES 5 */
var domtoimage = require('dom-to-image');

Bower

bower install dom-to-image

Include either src/dom-to-image.js or dist/dom-to-image.min.js in your page and it will make the domtoimage variable available in the global scope.

<script src="path/to/dom-to-image.min.js" />
<script>
  domtoimage.toPng(node)
  //...
</script>

Usage

All the top level functions accept DOM node and rendering options, and return promises, which are fulfilled with corresponding data URLs.
Get a PNG image base64-encoded data URL and display right away:

var node = document.getElementById('my-node');

domtoimage.toPng(node)
    .then(function (dataUrl) {
        var img = new Image();
        img.src = dataUrl;
        document.body.appendChild(img);
    })
    .catch(function (error) {
        console.error('oops, something went wrong!', error);
    });

Get a PNG image blob and download it (using FileSaver, for example):

domtoimage.toBlob(document.getElementById('my-node'))
    .then(function (blob) {
        window.saveAs(blob, 'my-node.png');
    });

Save and download a compressed JPEG image:

domtoimage.toJpeg(document.getElementById('my-node'), { quality: 0.95 })
    .then(function (dataUrl) {
        var link = document.createElement('a');
        link.download = 'my-image-name.jpeg';
        link.href = dataUrl;
        link.click();
    });

Get an SVG data URL, but filter out all the <i> elements:

function filter (node) {
    return (node.tagName !== 'i');
}

domtoimage.toSvg(document.getElementById('my-node'), {filter: filter})
    .then(function (dataUrl) {
        /* do something */
    });

Get the raw pixel data as a Uint8Array with every 4 array elements representing the RGBA data of a pixel:

var node = document.getElementById('my-node');

domtoimage.toPixelData(node)
    .then(function (pixels) {
        for (var y = 0; y < node.scrollHeight; ++y) {
          for (var x = 0; x < node.scrollWidth; ++x) {
            pixelAtXYOffset = (4 * y * node.scrollHeight) + (4 * x);
            /* pixelAtXY is a Uint8Array[4] containing RGBA values of the pixel at (x, y) in the range 0..255 */
            pixelAtXY = pixels.slice(pixelAtXYOffset, pixelAtXYOffset + 4);
          }
        }
    });

All the functions under impl are not public API and are exposed only for unit testing.


Rendering options

filter

A function taking DOM node as argument. Should return true if passed node should be included in the output (excluding node means excluding it's children as well). Not called on the root node.

bgcolor

A string value for the background color, any valid CSS color value.

height, width

Height and width in pixels to be applied to node before rendering.

style

An object whose properties to be copied to node's style before rendering. You might want to check this reference for JavaScript names of CSS properties.

quality

A number between 0 and 1 indicating image quality (e.g. 0.92 => 92%) of the JPEG image. Defaults to 1.0 (100%)

cacheBust

Set to true to append the current time as a query string to URL requests to enable cache busting. Defaults to false

imagePlaceholder

A data URL for a placeholder image that will be used when fetching an image fails. Defaults to undefined and will throw an error on failed images

Browsers

It's tested on latest Chrome and Firefox (49 and 45 respectively at the time of writing), with Chrome performing significantly better on big DOM trees, possibly due to it's more performant SVG support, and the fact that it supports CSSStyleDeclaration.cssText property.

Internet Explorer is not (and will not be) supported, as it does not support SVG <foreignObject> tag

Safari is not supported, as it uses a stricter security model on <foreignObject> tag. Suggested workaround is to use toSvg and render on the server.`

Dependencies

Source

Only standard lib is currently used, but make sure your browser supports:

Tests

Most importantly, tests depend on:

  • js-imagediff, to compare rendered and control images

  • ocrad.js, for the parts when you can't compare images (due to the browser rendering differences) and just have to test whether the text is rendered

How it works

There might some day exist (or maybe already exists?) a simple and standard way of exporting parts of the HTML to image (and then this script can only serve as an evidence of all the hoops I had to jump through in order to get such obvious thing done) but I haven't found one so far.

This library uses a feature of SVG that allows having arbitrary HTML content inside of the <foreignObject> tag. So, in order to render that DOM node for you, following steps are taken:

  1. Clone the original DOM node recursively

  2. Compute the style for the node and each sub-node and copy it to corresponding clone

    • and don't forget to recreate pseudo-elements, as they are not cloned in any way, of course
  3. Embed web fonts

    • find all the @font-face declarations that might represent web fonts

    • parse file URLs, download corresponding files

    • base64-encode and inline content as data: URLs

    • concatenate all the processed CSS rules and put them into one <style> element, then attach it to the clone

  4. Embed images

    • embed image URLs in <img> elements

    • inline images used in background CSS property, in a fashion similar to fonts

  5. Serialize the cloned node to XML

  6. Wrap XML into the <foreignObject> tag, then into the SVG, then make it a data URL

  7. Optionally, to get PNG content or raw pixel data as a Uint8Array, create an Image element with the SVG as a source, and render it on an off-screen canvas, that you have also created, then read the content from the canvas

  8. Done!

Things to watch out for

  • if the DOM node you want to render includes a <canvas> element with something drawn on it, it should be handled fine, unless the canvas is tainted - in this case rendering will rather not succeed.

  • at the time of writing, Firefox has a problem with some external stylesheets (see issue #13). In such case, the error will be caught and logged.

Authors

Anatolii Saienko, Paul Bakaus (original idea)

License

MIT