「コピー処理」は“ユーザーの手を 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 アプリにとっての “気の利いたショートカット” として
しっかり機能し始めます。
