コピーボタンの作り方|Clipboard API でテキストをコピー

Clipboard API でテキストをコピーする

navigator.clipboard.writeText() でテキストをクリップボードへコピーする方法を、3パターンで解説します。各デモと同じ動きを再現できるHTML・CSS・JavaScriptを掲載しています。
HTML・CSS・JSコードプレビューツールでも動作を確認できます。

① 基本実装 — 要素のテキストをコピーする

この文章をクリップボードにコピーできます。ペーストして確認してみてください。

まだコピーしていません

HTML
<p class="copy-target">コピーしたいテキスト</p>
<button class="copy-button" type="button">コピーする</button>
<p class="copy-feedback"></p>
CSS
.copy-target {
  margin: 0 0 12px;
  padding: 12px 16px;
  border: 1px solid #d8dee9;
  border-radius: 8px;
  background: #f8fafc;
  color: #334155;
  font-size: 14px;
  line-height: 1.7;
}

.copy-button {
  padding: 10px 24px;
  border: 1px solid #c4b5fd;
  border-radius: 8px;
  background: #fff;
  color: #5b21b6;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
}

.copy-feedback {
  margin: 12px 0 0;
  padding: 10px 14px;
  border: 1px solid #bbf7d0;
  border-radius: 8px;
  background: #f0fdf4;
  color: #166534;
  font-size: 14px;
  font-family: Consolas, "Courier New", monospace;
}
JS
var copyTarget = document.querySelector('.copy-target');
var copyButton = document.querySelector('.copy-button');
var copyFeedback = document.querySelector('.copy-feedback');

copyButton.addEventListener('click', function() {
  if (!navigator.clipboard) {
    copyFeedback.textContent = 'このブラウザは Clipboard API に未対応です。';
    return;
  }

  navigator.clipboard.writeText(copyTarget.textContent).then(function() {
    copyFeedback.textContent = 'コピーしました!ペーストして確認してみてください。';
  }, function() {
    copyFeedback.textContent = 'コピーに失敗しました。';
  });
});
navigator.clipboard.writeText(text)

渡した文字列をクリップボードへ書き込む非同期メソッドです。Promise を返すので、成功時と失敗時を .then() で分けて書けます。要素の表示テキストを取るときは textContent を使います。冒頭で navigator.clipboard の有無を確認すると、未対応ブラウザで止まりにくくなります。

② テキストエリア — 入力内容を .value でコピーする

まだコピーしていません

HTML
<textarea class="copy-area" rows="3">コピーしたいテキスト</textarea>
<button class="copy-area-button" type="button">テキストをコピー</button>
<p class="copy-area-feedback"></p>
CSS
.copy-area {
  display: block;
  width: 100%;
  max-width: 420px;
  min-height: 80px;
  margin: 0 0 12px;
  padding: 10px 14px;
  border: 1px solid #d8dee9;
  border-radius: 8px;
  background: #fff;
  color: #334155;
  font-size: 14px;
  font-family: Consolas, "Courier New", monospace;
  line-height: 1.6;
  box-sizing: border-box;
  resize: vertical;
}

.copy-area-button {
  padding: 10px 24px;
  border: 1px solid #6ee7b7;
  border-radius: 8px;
  background: #fff;
  color: #047857;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
}

.copy-area-feedback {
  margin: 12px 0 0;
  padding: 10px 14px;
  border: 1px solid #bbf7d0;
  border-radius: 8px;
  background: #f0fdf4;
  color: #166534;
  font-size: 14px;
  font-family: Consolas, "Courier New", monospace;
}
JS
var copyArea = document.querySelector('.copy-area');
var copyAreaButton = document.querySelector('.copy-area-button');
var copyAreaFeedback = document.querySelector('.copy-area-feedback');

copyAreaButton.addEventListener('click', function() {
  if (!navigator.clipboard) {
    copyAreaFeedback.textContent = 'このブラウザは Clipboard API に未対応です。';
    return;
  }

  navigator.clipboard.writeText(copyArea.value).then(function() {
    copyAreaFeedback.textContent = 'コピーしました!';
  }, function() {
    copyAreaFeedback.textContent = 'コピーに失敗しました。';
  });
});
textarea / input は .value を使う

フォーム要素の内容は textContent ではなく value で取ります。ユーザーが編集した最新の文字列がそのままコピーできるので、「コードを書き換えてコピー」のような用途に向いています。

③ ビジュアルフィードバック — alert を使わない完了通知

NOVEBLO AI Design — navigator.clipboard.writeText()

HTML
<p class="copy-visual-target">コピー対象のテキスト</p>
<button class="copy-visual-button" type="button">テキストをコピー</button>
CSS
.copy-visual-target {
  margin: 0 0 12px;
  padding: 14px 18px;
  border: 1px dashed #cbd5e1;
  border-radius: 8px;
  background: #f8fafc;
  color: #334155;
  font-size: 14px;
  font-family: Consolas, "Courier New", monospace;
}

.copy-visual-button {
  min-width: 180px;
  padding: 10px 24px;
  border: 1px solid #fcd34d;
  border-radius: 8px;
  background: #fff;
  color: #92400e;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}

.copy-visual-button.is-done {
  background: #dcfce7;
  color: #166534;
  border-color: #86efac;
}
JS
var copyVisualTarget = document.querySelector('.copy-visual-target');
var copyVisualButton = document.querySelector('.copy-visual-button');

copyVisualButton.addEventListener('click', function() {
  if (!navigator.clipboard) return;

  navigator.clipboard.writeText(copyVisualTarget.textContent).then(function() {
    copyVisualButton.textContent = 'コピー完了!';
    copyVisualButton.className = 'copy-visual-button is-done';

    setTimeout(function() {
      copyVisualButton.textContent = 'テキストをコピー';
      copyVisualButton.className = 'copy-visual-button';
    }, 2000);
  });
});
ボタン自身をフィードバックにする

コピー完了を alert で出すと操作が止まります。ボタンの文言と色を一時変更し、setTimeout で元に戻すと、ページを中断せずに結果が伝わります。状態クラスはベースのクラス名を残したまま付け外ししてください。

注意点:navigator.clipboard は HTTPS または localhost でのみ使えます。HTTP では undefined になり、コピーできません。冒頭の有無チェックに加え、失敗時のメッセージ表示も入れておくと安全です。また、ユーザー操作(クリックなど)の直後でないと拒否されるブラウザもあります。

textContent と value はどちらを使いますか?

pspan など通常の要素は textContenttextareainputvalue です。フォーム要素に textContent を使うと、ユーザーが編集した内容ではなく初期HTML側の文字を取ってしまうことがあります。

コピーできません。原因は何が多いですか?

多いのは HTTP で開いているクリック以外のタイミングで呼んでいる権限やブラウザ未対応 です。デモと同じく、ボタンの click ハンドラ内で writeText を呼び、失敗時も表示するようにしてください。

alert で「コピーしました」と出してもいいですか?

動きますが、操作が止まるのでおすすめしません。③のデモのようにボタンの見た目で伝えるか、軽い通知ならトースト通知も選択肢です。

古いブラウザ向けのフォールバックは必要ですか?

学習や社内ツールなら Clipboard API だけで十分なことが多いです。古い方式のフォールバックもありますが、新規実装の第一選択にはしません。まず未対応メッセージを出す方が安全です。


当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次