clipboard vs clipboard-polyfill vs copy-to-clipboard vs react-copy-to-clipboard vs vue-clipboard2
Web アプリケーションにおけるクリップボード操作の実装戦略
clipboardclipboard-polyfillcopy-to-clipboardreact-copy-to-clipboardvue-clipboard2類似パッケージ:

Web アプリケーションにおけるクリップボード操作の実装戦略

clipboardclipboard-polyfillcopy-to-clipboardreact-copy-to-clipboardvue-clipboard2 はすべて、Web アプリケーションからユーザーのシステムクリップボードにテキストをコピーする機能を提供する npm パッケージです。これらのライブラリは、document.execCommand('copy') のような古い API や、現代の navigator.clipboard.writeText() Web API をラップまたはポリフィルすることで、クロスブラウザで安全かつ信頼性の高いコピー動作を実現します。各パッケージは異なる設計哲学と統合戦略を持っており、特にフレームワーク依存性(React/Vue 向け vs フレームワーク非依存)、ポリフィルの必要性、API の使いやすさにおいて差異があります。

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

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
clipboard034,13894.5 kB15-MIT
clipboard-polyfill0927404 kB92年前MIT
copy-to-clipboard01,39833.5 kB152ヶ月前MIT
react-copy-to-clipboard02,37337.9 kB144ヶ月前MIT
vue-clipboard201,753-375年前MIT

クリップボード操作ライブラリ徹底比較:clipboard、clipboard-polyfill、copy-to-clipboard、react-copy-to-clipboard、vue-clipboard2

Web アプリで「コピー」ボタンを実装するのは一見簡単ですが、実際にはブラウザのセキュリティ制限、API の進化、フレームワークとの統合など、多くの技術的課題があります。この記事では、代表的な5つの npm パッケージを、実際のコードと開発シナリオに基づいて深く比較します。

🧩 基本的な使い方:1行でコピーできるか?

まず、最も単純なケース —— 任意の文字列をプログラムでコピーする —— で各ライブラリの使い勝手を確認します。

clipboard は DOM 要素に依存するため、直接文字列を渡せません。代わりに、data-clipboard-text 属性を持つ要素が必要です。

// clipboard: DOM 要素必須
import Clipboard from 'clipboard';

const btn = document.createElement('button');
btn.setAttribute('data-clipboard-text', 'Hello, world!');
document.body.appendChild(btn);

new Clipboard(btn);
// ボタンクリックでコピーされる(プログラムによる即時コピー不可)

clipboard-polyfill は Promise ベースのシンプルな関数呼び出しで動作します。

// clipboard-polyfill
import { writeText } from 'clipboard-polyfill';

writeText('Hello, world!').catch(err => console.error(err));

copy-to-clipboard も同様に、関数1つでコピー可能です。

// copy-to-clipboard
import copy from 'copy-to-clipboard';

copy('Hello, world!'); // boolean を返す(成功/失敗)

react-copy-to-clipboard は React コンポーネントとして使用します。

// react-copy-to-clipboard
import { CopyToClipboard } from 'react-copy-to-clipboard';

function App() {
  return (
    <CopyToClipboard text="Hello, world!">
      <button>コピー</button>
    </CopyToClipboard>
  );
}

vue-clipboard2 は Vue ディレクティブでバインドします(Vue 2 限定)。

// vue-clipboard2 (Vue 2)
import Vue from 'vue';
import VueClipboard from 'vue-clipboard2';

Vue.use(VueClipboard);

// テンプレート内
// <button v-clipboard:copy="'Hello, world!'">コピー</button>

💡 ポイント: clipboard 以外は、DOM 要素を介さずに直接文字列をコピーできます。ただし、react-copy-to-clipboardvue-clipboard2 はそれぞれのフレームワークに強く依存しています。

🔒 セキュリティとブラウザ互換性:どの API を使うか?

現代のブラウザでは、navigator.clipboard.writeText() が標準ですが、これは HTTPS または localhost でのみ動作します。一方、古い document.execCommand('copy') は任意のコンテキストで動作しますが、非推奨です。

clipboardexecCommand のみ を使用します。そのため、最新ブラウザでも非推奨 API に依存し続けます。

clipboard-polyfillClipboard API を優先し、サポートされていない環境では execCommand にフォールバックします。さらに、iOS Safari の特殊な挙動にも対応しています。

copy-to-clipboard も同様に、モダン API を優先し、必要に応じて execCommand にフォールバックします。

react-copy-to-clipboard は内部で copy-to-clipboard を使用しているため、同じ互換性戦略を持ちます。

vue-clipboard2clipboard ライブラリに依存しており、execCommand のみ を使用します。

⚠️ 注意: clipboardvue-clipboard2 は非推奨 API に依存しているため、新しいプロジェクトでは避けるべきです。特に、モバイル Safari や今後のブラウザアップデートで動作しなくなるリスクがあります。

🧪 エラーハンドリング:失敗をどう扱うか?

コピー操作は常に成功するとは限りません(例: ユーザーが権限を拒否した場合)。各ライブラリのエラー処理方法を比較します。

clipboard-polyfill は Promise を返すため、catch でエラーを捕捉できます。

writeText('text').catch(err => {
  console.error('コピー失敗:', err.message);
});

copy-to-clipboard は成功時に true、失敗時に false を返します。

const success = copy('text');
if (!success) {
  console.warn('コピーに失敗しました');
}

clipboardvue-clipboard2 はイベントリスナー経由で結果を取得します。

const clipboard = new Clipboard(btn);
clipboard.on('error', e => console.error('コピー失敗'));

react-copy-to-clipboardonCopy コールバックで結果を通知します。

<CopyToClipboard text="text" onCopy={(text, result) => {
  if (!result) console.warn('コピー失敗');
}}>
  <button>コピー</button>
</CopyToClipboard>

💡 実践的アドバイス: Promise ベースの clipboard-polyfill は非同期処理との統合が容易で、モダンなコードベースに適しています。一方、copy-to-clipboard の boolean 返り値はシンプルで直感的です。

🧱 フレームワーク統合:React/Vue でどう使うか?

React での使用

  • react-copy-to-clipboard は JSX に自然に組み込めますが、カスタムロジック(例: 成功時のトースト表示)を追加するには onCopy を使う必要があります。
  • copy-to-clipboard を直接使うと、より柔軟な制御が可能です。
// copy-to-clipboard を React で使う例
import { useState } from 'react';
import copy from 'copy-to-clipboard';

function CopyButton({ text }) {
  const [copied, setCopied] = useState(false);

  const handleClick = () => {
    if (copy(text)) {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    }
  };

  return <button onClick={handleClick}>{copied ? 'コピー済み' : 'コピー'}</button>;
}

Vue での使用

  • vue-clipboard2 は Vue 2 専用であり、Vue 3 では動作しません。Vue 3 プロジェクトでは、copy-to-clipboard を Composition API でラップするのが現実的です。
// Vue 3 + copy-to-clipboard の例
import { ref } from 'vue';
import copy from 'copy-to-clipboard';

export function useClipboard() {
  const copied = ref(false);

  const copyText = (text) => {
    if (copy(text)) {
      copied.value = true;
      setTimeout(() => copied.value = false, 2000);
    }
  };

  return { copied, copyText };
}

🚫 非推奨とメンテナンス状況

公式情報によると:

  • clipboard は GitHub リポジトリで「このプロジェクトはメンテナンスされていません」と明記されており、新しいプロジェクトでの使用は推奨されません
  • vue-clipboard2 は Vue 3 に対応しておらず、最終更新が古いため、Vue 2 レガシープロジェクト以外では避けるべきです。

一方、clipboard-polyfillcopy-to-clipboard は積極的にメンテナンスされており、最新のブラウザ変更にも追随しています。

📊 まとめ:どのライブラリを選ぶべきか?

ライブラリ推奨用途フレームワーク依存モダン API 対応新規プロジェクト向け
clipboardレガシーな静的サイトなし
clipboard-polyfillクロスブラウザ対応が必要な汎用アプリなし✅(ポリフィル付き)
copy-to-clipboardシンプルで軽量なコピー機能なし✅(自動フォールバック)
react-copy-to-clipboardReact 専用の簡易実装React✅(内部で copy-to-clipboard 使用)△(小規模向け)
vue-clipboard2Vue 2 レガシープロジェクトVue 2

💡 最終的なアドバイス

  • フレームワーク非依存で確実に動作させたいclipboard-polyfill(完全なポリフィル)または copy-to-clipboard(軽量)
  • React プロジェクトで素早く実装したいreact-copy-to-clipboard(ただし、カスタムロジックが必要なら copy-to-clipboard 直接使用が柔軟)
  • Vue 3 プロジェクトcopy-to-clipboard を Composition API でラップ
  • 新しいプロジェクトで clipboardvue-clipboard2 を使うのは避けてください。非推奨 API への依存は将来的な破壊的変更を招きます。

クリップボード操作は「小さな機能」に見えますが、ユーザー体験に直結します。信頼性と将来性を考えて、適切なツールを選びましょう。

選び方: clipboard vs clipboard-polyfill vs copy-to-clipboard vs react-copy-to-clipboard vs vue-clipboard2

  • clipboard:

    clipboard は DOM 要素に直接バインドして動作する軽量なライブラリです。ボタンクリックなどのイベント発火時に特定の要素の内容や属性値をコピーしたい場合に最適です。ただし、execCommand に依存しており、モダンな Clipboard API には対応していません。新しいプロジェクトでは、セキュリティ制限や非推奨化のリスクを考慮し、代替手段を検討すべきです。

  • clipboard-polyfill:

    clipboard-polyfillnavigator.clipboard.writeText() の完全なポリフィルを提供し、古いブラウザでも動作するように設計されています。フレームワークに依存せず、純粋な JavaScript 環境で一貫した API を使いたい場合に最適です。特に、セキュリティコンテキスト(HTTPS や localhost)外でも動作させる必要があるレガシー環境向けに有用ですが、最新ブラウザのみをターゲットにする場合はオーバーヘッドになる可能性があります。

  • copy-to-clipboard:

    copy-to-clipboard はシンプルな関数ベースの API を持ち、任意の文字列をコピーするための最小限のユーティリティです。React や Vue などのフレームワークに依存せず、軽量で直感的に使用できます。モダンブラウザでは Clipboard API を、古い環境では execCommand を内部で自動的に切り替えて使用するため、バランスの取れた選択肢です。複雑な DOM 操作やトリガー要素不要なケースに最適です。

  • react-copy-to-clipboard:

    react-copy-to-clipboard は React 専用のコンポーネントとして設計されており、JSX 内で宣言的にコピー機能を実装できます。<CopyToClipboard> コンポーネントに text プロパティを渡すだけで、子要素のクリックでコピーが発火します。React プロジェクトで迅速にコピー UI を実装したい場合に便利ですが、React 以外の環境では使用できません。内部では copy-to-clipboard パッケージを利用しています。

  • vue-clipboard2:

    vue-clipboard2 は Vue 2 向けのディレクティブ (v-clipboard) を提供し、Vue コンポーネント内で簡単にクリップボード機能をバインドできます。Vue 2 プロジェクトで既存のボタンや要素にコピー動作を追加したい場合に最適です。ただし、Vue 3 には正式に対応しておらず、メンテナンス状況を確認する必要があります。新しい Vue プロジェクトでは、代わりに @vueuse/coreuseClipboard などを検討すべきです。

clipboard のREADME

clipboard.js

Build Status Killing Flash

Modern copy to clipboard. No Flash. Just 3kb gzipped.

Demo

Why

Copying text to the clipboard shouldn't be hard. It shouldn't require dozens of steps to configure or hundreds of KBs to load. But most of all, it shouldn't depend on Flash or any bloated framework.

That's why clipboard.js exists.

Install

You can get it on npm.

npm install clipboard --save

Or if you're not into package management, just download a ZIP file.

Setup

First, include the script located on the dist folder or load it from a third-party CDN provider.

<script src="dist/clipboard.min.js"></script>

Now, you need to instantiate it by passing a DOM selector, HTML element, or list of HTML elements.

new ClipboardJS('.btn');

Internally, we need to fetch all elements that matches with your selector and attach event listeners for each one. But guess what? If you have hundreds of matches, this operation can consume a lot of memory.

For this reason we use event delegation which replaces multiple event listeners with just a single listener. After all, #perfmatters.

Usage

We're living a declarative renaissance, that's why we decided to take advantage of HTML5 data attributes for better usability.

Copy text from another element

A pretty common use case is to copy content from another element. You can do that by adding a data-clipboard-target attribute in your trigger element.

The value you include on this attribute needs to match another's element selector.

example-2

<!-- Target -->
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git" />

<!-- Trigger -->
<button class="btn" data-clipboard-target="#foo">
  <img src="https://raw.githubusercontent.com/zenorocha/clipboard.js/HEAD/assets/clippy.svg" alt="Copy to clipboard" />
</button>

Cut text from another element

Additionally, you can define a data-clipboard-action attribute to specify if you want to either copy or cut content.

If you omit this attribute, copy will be used by default.

example-3

<!-- Target -->
<textarea id="bar">Mussum ipsum cacilds...</textarea>

<!-- Trigger -->
<button class="btn" data-clipboard-action="cut" data-clipboard-target="#bar">
  Cut to clipboard
</button>

As you may expect, the cut action only works on <input> or <textarea> elements.

Copy text from attribute

Truth is, you don't even need another element to copy its content from. You can just include a data-clipboard-text attribute in your trigger element.

example-1

<!-- Trigger -->
<button
  class="btn"
  data-clipboard-text="Just because you can doesn't mean you should — clipboard.js"
>
  Copy to clipboard
</button>

Events

There are cases where you'd like to show some user feedback or capture what has been selected after a copy/cut operation.

That's why we fire custom events such as success and error for you to listen and implement your custom logic.

var clipboard = new ClipboardJS('.btn');

clipboard.on('success', function (e) {
  console.info('Action:', e.action);
  console.info('Text:', e.text);
  console.info('Trigger:', e.trigger);

  e.clearSelection();
});

clipboard.on('error', function (e) {
  console.error('Action:', e.action);
  console.error('Trigger:', e.trigger);
});

For a live demonstration, go to this site and open your console.

Tooltips

Each application has different design needs, that's why clipboard.js does not include any CSS or built-in tooltip solution.

The tooltips you see on the demo site were built using GitHub's Primer. You may want to check that out if you're looking for a similar look and feel.

Advanced Options

If you don't want to modify your HTML, there's a pretty handy imperative API for you to use. All you need to do is declare a function, do your thing, and return a value.

For instance, if you want to dynamically set a target, you'll need to return a Node.

new ClipboardJS('.btn', {
  target: function (trigger) {
    return trigger.nextElementSibling;
  },
});

If you want to dynamically set a text, you'll return a String.

new ClipboardJS('.btn', {
  text: function (trigger) {
    return trigger.getAttribute('aria-label');
  },
});

For use in Bootstrap Modals or with any other library that changes the focus you'll want to set the focused element as the container value.

new ClipboardJS('.btn', {
  container: document.getElementById('modal'),
});

Also, if you are working with single page apps, you may want to manage the lifecycle of the DOM more precisely. Here's how you clean up the events and objects that we create.

var clipboard = new ClipboardJS('.btn');
clipboard.destroy();

Browser Support

This library relies on both Selection and execCommand APIs. The first one is supported by all browsers while the second one is supported in the following browsers.

Chrome logoEdge logoFirefox logoInternet Explorer logoOpera logoSafari logo
42+ ✔12+ ✔41+ ✔9+ ✔29+ ✔10+ ✔

The good news is that clipboard.js gracefully degrades if you need to support older browsers. All you have to do is show a tooltip saying Copied! when success event is called and Press Ctrl+C to copy when error event is called because the text is already selected.

You can also check if clipboard.js is supported or not by running ClipboardJS.isSupported(), that way you can hide copy/cut buttons from the UI.

Bonus

A browser extension that adds a "copy to clipboard" button to every code block on GitHub, MDN, Gist, StackOverflow, StackExchange, npm, and even Medium.

Install for Chrome and Firefox.

License

MIT License © Zeno Rocha