JavaScript | Web API:クリップボード・共有 - コピー処理

JavaScript JavaScript
スポンサーリンク

「コピー処理」は“ユーザーの手を 1 回減らす”ための仕組み

コピー処理は、
ユーザーが本来やるはずだった

  • テキストをドラッグで選択
  • Ctrl+C / 右クリック → コピー

という手順を、ボタン 1 回で代わりにやってあげるイメージです。

JavaScript でコピー処理を実装するときの主役は、
今の時代は Clipboard API(navigator.clipboard.writeText です。

昔ながらの document.execCommand("copy") もありますが、
非推奨で挙動も不安定なので、
初心者のうちから Clipboard API に慣れておくのがおすすめです。


一番基本のコピー処理:writeText で文字列をクリップボードに送る

最小の「コピー」ボタンの例

HTML:

<div id="text">このテキストをコピーします</div>
<button id="copyBtn">コピー</button>
<div id="status"></div>

JavaScript:

const textEl = document.querySelector("#text");
const copyBtn = document.querySelector("#copyBtn");
const statusEl = document.querySelector("#status");

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

  try {
    await navigator.clipboard.writeText(text);
    statusEl.textContent = "コピーしました!";
  } catch (err) {
    statusEl.textContent = "コピーに失敗しました: " + err;
  }
});
JavaScript

ここでしっかり理解してほしいポイントは 3 つあります。

1. navigator.clipboard.writeText は「非同期」である

navigator.clipboard.writeText(text) は、
すぐに終わるとは限らない処理です。
ブラウザが OS のクリップボードにアクセスしたり、
権限を確認したりする必要があるからです。

そのため、この関数は Promise を返します
async/await を使うと読みやすく書けます。

await navigator.clipboard.writeText(text);
JavaScript

と書くことで、
「コピーが完了するまで待ってから次の行に進む」
という流れになります。

2. 失敗する可能性を前提にする(try…catch)

クリップボードへのアクセスは、
ブラウザや環境によって拒否されることがあります。

例えば、

  • HTTPS でない
  • ブラウザが Clipboard API に対応していない
  • ユーザーが権限を拒否した

などの理由で失敗することがあります。

だからこそ、try...catch で囲んでおくのが大事です。

try {
  await navigator.clipboard.writeText(text);
  // 成功時の処理
} catch (err) {
  // 失敗時の処理
}
JavaScript

「コピーできなかったときにどう振る舞うか」まで考えるのが、
“ちゃんとしたコピー処理”です。

3. ユーザー操作に紐づけて呼ぶ

Clipboard API は、
セキュリティ上の理由から ユーザー操作に紐づいていないと動かない ことが多いです。

つまり、

  • ページ読み込み直後に勝手にコピー
  • setTimeout で勝手にコピー

のようなことは基本的にできません。

ボタンの click イベントの中で呼ぶ、
あるいは keydown(ショートカット)など、
「ユーザーが何かした瞬間」に呼ぶのが前提です。


よくある UI パターン:コードスニペットの「コピー」ボタン

「コピーしました」のフィードバックを必ず出す

コピー処理は、
ユーザーから見て「本当にコピーされたのか」が分かりにくいです。

なので、フィードバックを出すのがほぼ必須です。

HTML:

<pre id="code">npm install awesome-lib</pre>
<button id="copyCodeBtn">コピー</button>
<span id="copyMessage"></span>

JavaScript:

const codeEl = document.querySelector("#code");
const copyCodeBtn = document.querySelector("#copyCodeBtn");
const copyMessage = document.querySelector("#copyMessage");

copyCodeBtn.addEventListener("click", async () => {
  const text = codeEl.textContent;

  try {
    await navigator.clipboard.writeText(text);
    copyMessage.textContent = "コピーしました";
    setTimeout(() => {
      copyMessage.textContent = "";
    }, 1500);
  } catch {
    copyMessage.textContent = "コピーできませんでした";
  }
});
JavaScript

ここでのポイントは、

  • 成功時に「コピーしました」と表示
  • 少し時間が経ったらメッセージを消す
  • 失敗時には別のメッセージを出す

という「人間にとって分かりやすい振る舞い」をしていることです。

コピー処理は技術的には一行ですが、
「ユーザーにとって安心できる体験」にするには、周辺の UI が大事です。


テキストエリアの内容をコピーするパターン

入力欄の内容を丸ごとコピー

HTML:

<textarea id="memo" rows="4" cols="40" placeholder="ここに入力した内容をコピーします"></textarea>
<button id="copyMemoBtn">コピー</button>
<div id="memoStatus"></div>

JavaScript:

const memo = document.querySelector("#memo");
const copyMemoBtn = document.querySelector("#copyMemoBtn");
const memoStatus = document.querySelector("#memoStatus");

copyMemoBtn.addEventListener("click", async () => {
  const text = memo.value;

  if (!text) {
    memoStatus.textContent = "コピーする内容がありません";
    return;
  }

  try {
    await navigator.clipboard.writeText(text);
    memoStatus.textContent = "コピーしました";
  } catch {
    memoStatus.textContent = "コピーに失敗しました";
  }
});
JavaScript

ここでの大事なポイントは、
「空文字のときはコピーしない」 というチェックを入れていることです。

こういう小さな気配りが、
「雑なコピー機能」と「ちゃんとしたコピー機能」の差になります。


Clipboard API が使えない場合のフォールバックをどう考えるか

navigator.clipboard がない環境も一応想定する

古いブラウザや、
特殊な環境では navigator.clipboard 自体が存在しないことがあります。

その場合は、
「コピー機能は使えません」と割り切るか、
古い execCommand("copy") ベースのフォールバックを用意するか、
どちらかの選択になります。

最低限のチェックはこうです。

if (!navigator.clipboard) {
  alert("このブラウザではコピー機能が利用できません");
  return;
}
JavaScript

実務では、
ライブラリ(clipboard.js など)に任せることも多いですが、
「内部では Clipboard API と execCommand をうまく切り替えている」
というイメージを持っておくと理解が深まります。


コピー処理を設計するときに意識してほしいこと

コピー処理は「一行で終わるテクニック」ではなく、
「ユーザーの行動をどれだけスムーズにするか」という設計の一部です。

そのために、次の視点を持っておくといいです。

ユーザーが「どのテキストをコピーしたいのか」が一目で分かるようにする。
コピー後に「本当にコピーされたのか」が分かるフィードバックを出す。
失敗する可能性を前提にして、メッセージやフォールバックを用意する。
クリックなどのユーザー操作に紐づけて Clipboard API を呼ぶ。

まずは次の 2 つを、自分の手で書いてみてください。

任意のテキストをコピーする「コピー」ボタン(成功/失敗メッセージ付き)。
コードスニペットの横に「コピー」ボタンを置き、押すとそのコードがコピーされる UI。

これが自然に書けるようになったとき、
コピー処理は単なる「小技」ではなく、
あなたの Web アプリにとっての “気の利いたショートカット” として
しっかり機能し始めます。

タイトルとURLをコピーしました