【JavaScript】クリップボードにコピーする方法|Clipboard API・writeText・フォールバック・コピー成功通知・HTTPS 制限まで解説

招待コードのコピー、共有 URL のワンクリックコピー、コードブロックのコピーボタンなど、クリップボードにテキストをコピーする機能はモダンな Web アプリで広く使われています。JavaScript では Clipboard API を使うのが推奨される方法です。

この記事でわかること
・Clipboard API(navigator.clipboard.writeText)の基本
・execCommand の旧方式とフォールバック
・HTTPS / localhost 制限と対処法
・コピー成功時のユーザーフィードバック(ボタン変更・トースト通知)
・readText でクリップボードから読み取る方法
・ClipboardItem でリッチコンテンツ(HTML・画像)をコピーする方法
・コードブロックのコピーボタン・共有 URL・招待コードの実務パターン
スポンサーリンク

Clipboard API でテキストをコピーする(推奨)

navigator.clipboard.writeText() は、テキストをクリップボードにコピーするためのモダンで推奨される方法です。非同期(Promise)で動作し、エラーハンドリングも容易です。

JavaScript
async function copyToClipboard(text) {
  try {
    await navigator.clipboard.writeText(text);
    console.log("コピーしました:", text);
  } catch (err) {
    console.error("コピーに失敗しました:", err);
  }
}

// ボタンクリックでコピー
document.getElementById("copyBtn").addEventListener("click", () => {
  copyToClipboard("コピーするテキスト");
});

input / textarea の値をコピーする

JavaScript
document.getElementById("copyBtn").addEventListener("click", async () => {
  const text = document.getElementById("inputField").value;
  await navigator.clipboard.writeText(text);
});

要素のテキストをコピーする

JavaScript
document.getElementById("copyBtn").addEventListener("click", async () => {
  const text = document.getElementById("codeBlock").textContent;
  await navigator.clipboard.writeText(text);
});

HTTPS / localhost 制限

Clipboard API はセキュリティ上の理由から、以下の条件でのみ動作します。

環境 動作 備考
HTTPS ○ 動作する 本番環境の標準
localhost ○ 動作する 開発環境
HTTP(非 localhost) × 動作しない navigator.clipboard が undefined
file:// プロトコル × 動作しない ローカルファイルを直接開いた場合
HTTP 環境で navigator.clipboardundefined になる場合は、後述の execCommand フォールバックを使ってください。

execCommand によるフォールバック(旧方式)

document.execCommand("copy") は非推奨ですが、Clipboard API が使えない環境へのフォールバックとして有用です。

JavaScript
function fallbackCopyText(text) {
  const textarea = document.createElement("textarea");
  textarea.value = text;

  // 画面外に配置(ちらつき防止)
  textarea.style.position = "fixed";
  textarea.style.left = "-9999px";
  textarea.style.top = "-9999px";

  document.body.appendChild(textarea);
  textarea.select();

  try {
    document.execCommand("copy");
    console.log("コピーしました(fallback)");
  } catch (err) {
    console.error("コピーに失敗しました:", err);
  }

  document.body.removeChild(textarea);
}

Clipboard API + フォールバックの統合関数

JavaScript
async function copyText(text) {
  if (navigator.clipboard && window.isSecureContext) {
    // Clipboard API が使える環境
    await navigator.clipboard.writeText(text);
  } else {
    // フォールバック
    fallbackCopyText(text);
  }
}
window.isSecureContext で安全なコンテキスト(HTTPS / localhost)かどうかを判定できます。Clipboard API の可用性チェックに使いましょう。

コピー成功時のユーザーフィードバック

コピーが成功したことをユーザーに伝えるフィードバックは UX の観点で重要です。

ボタンのテキストを一時的に変更する

JavaScript
const copyBtn = document.getElementById("copyBtn");

copyBtn.addEventListener("click", async () => {
  const text = document.getElementById("code").textContent;

  try {
    await navigator.clipboard.writeText(text);

    // ボタンテキストを変更
    const original = copyBtn.textContent;
    copyBtn.textContent = "コピーしました!";
    copyBtn.disabled = true;

    // 2秒後に元に戻す
    setTimeout(() => {
      copyBtn.textContent = original;
      copyBtn.disabled = false;
    }, 2000);
  } catch (err) {
    copyBtn.textContent = "コピー失敗";
  }
});

トースト通知を表示する

JavaScript
function showToast(message, duration = 2000) {
  const toast = document.createElement("div");
  toast.className = "toast";
  toast.textContent = message;
  document.body.appendChild(toast);

  // フェードインのため少し遅延
  requestAnimationFrame(() => toast.classList.add("show"));

  setTimeout(() => {
    toast.classList.remove("show");
    toast.addEventListener("transitionend", () => toast.remove());
  }, duration);
}
CSS
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: #333;
  color: #fff;
  padding: 12px 24px;
  border-radius: 8px;
  opacity: 0;
  transition: opacity 0.3s ease, transform 0.3s ease;
  z-index: 9999;
}
.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

クリップボードから読み取る(readText)

navigator.clipboard.readText() でクリップボードの内容を読み取れます。ただし、ユーザーの許可ダイアログが表示されます。

JavaScript
async function pasteFromClipboard() {
  try {
    const text = await navigator.clipboard.readText();
    console.log("クリップボードの内容:", text);
    return text;
  } catch (err) {
    console.error("読み取りに失敗:", err);
    return null;
  }
}
readText はユーザーの許可が必要です。ユーザーが拒否した場合は DOMException: Read permission denied エラーが発生します。writeText(コピー)は許可なしで動作します。

ClipboardItem でリッチコンテンツをコピーする

navigator.clipboard.write()ClipboardItem を使うと、プレーンテキスト以外の形式(HTML、画像など)もクリップボードにコピーできます。

HTML をコピー
async function copyHTML(htmlString) {
  const blob = new Blob([htmlString], { type: "text/html" });
  const item = new ClipboardItem({ "text/html": blob });
  await navigator.clipboard.write([item]);
}

// 太字テキストとしてコピー
copyHTML("<strong>重要なお知らせ</strong>");
// → Word や Gmail に貼り付けると太字で表示される
メソッド コピー対象 用途
writeText(text) プレーンテキスト 一般的なテキストコピー
write([ClipboardItem]) HTML・画像・複数形式 リッチテキスト・スクリーンショット

実務でよく使うパターン

コードブロックにコピーボタンを追加する

JavaScript
document.querySelectorAll("pre").forEach(pre => {
  const btn = document.createElement("button");
  btn.className = "copy-btn";
  btn.textContent = "コピー";

  btn.addEventListener("click", async () => {
    await navigator.clipboard.writeText(pre.textContent);
    btn.textContent = "コピー済み";
    setTimeout(() => btn.textContent = "コピー", 2000);
  });

  // pre の親要素に相対配置を設定してボタンを右上に配置
  pre.style.position = "relative";
  btn.style.cssText = "position:absolute;top:8px;right:8px;";
  pre.appendChild(btn);
});

現在のページ URL をコピーする

JavaScript
document.getElementById("shareBtn").addEventListener("click", async () => {
  await navigator.clipboard.writeText(window.location.href);
  showToast("URLをコピーしました");
});

招待コード / クーポンコードをコピーする

HTML
<div class="coupon">
  <span id="couponCode">SAVE20OFF</span>
  <button id="copyCoupon">コピー</button>
</div>
JavaScript
document.getElementById("copyCoupon").addEventListener("click", async () => {
  const code = document.getElementById("couponCode").textContent;
  await navigator.clipboard.writeText(code);

  const btn = document.getElementById("copyCoupon");
  btn.textContent = "コピー済み ✓";
  setTimeout(() => btn.textContent = "コピー", 2000);
});

関連記事

よくある質問

QClipboard API が動作しません。
AClipboard API はHTTPS または localhostでのみ動作します。HTTP 環境では navigator.clipboardundefined になります。window.isSecureContext で判定し、非安全な環境では execCommand フォールバックを使ってください。
Qユーザーの操作なしで自動的にコピーできますか?
Aいいえ。Clipboard API はセキュリティ上の理由から、ユーザーの直接的な操作(クリックなど)に応じてのみ動作します。ページ読み込み時に自動コピーすることはできません。
QwriteText と write の違いは何ですか?
AwriteText はプレーンテキスト専用で簡単に使えます。writeClipboardItem を使って HTML や画像などリッチコンテンツもコピーできます。通常のテキストコピーには writeText で十分です。
Qコピーが成功したことをユーザーにどう伝えますか?
Aボタンのテキストを一時的に「コピーしました!」に変更し、setTimeout で元に戻す方法が最も一般的です。または画面下部にトースト通知を表示する方法もあります。
QexecCommand(“copy”) はまだ使えますか?
A2026 年現在、主要ブラウザではまだ動作しますが公式に非推奨です。新規開発では Clipboard API を使い、execCommand はフォールバックとしてのみ残してください。

まとめ

JavaScript でクリップボードにコピーする方法を整理しました。

  • 推奨: navigator.clipboard.writeText(text)(非同期・シンプル)
  • フォールバック: execCommand("copy")(HTTP 環境向け・非推奨)
  • 統合関数: isSecureContext で判定して自動切り替え
  • HTTPS 制限: Clipboard API は安全なコンテキストでのみ動作
  • フィードバック: ボタンテキスト変更 or トースト通知
  • リッチコンテンツ: ClipboardItem で HTML・画像もコピー可能

コードブロックのコピーボタンや共有 URL のコピーは、ユーザー体験を大きく向上させる定番機能です。Clipboard API + フォールバックの統合関数を用意しておけば、あらゆる環境に対応できます。