コピーボタン付きテキストボックスは、入力した文字や文章を選択せずに、ボタンを押すだけでクリップボードにコピーできる入力欄です。入力内容はJavaScriptで取得してコピーするため、コピー後も入力欄の文字はそのまま残ります。
今回は、1行入力のテキストフィールドと複数行入力のテキストエリアを使った2種類のサンプルを紹介します。1つ目は入力欄の右端にSVGのコピーアイコンを配置し、コピーに成功するとチェックアイコンへふわっと切り替わります。2つ目は入力欄の下にコピーボタンを配置し、改行を含む文章をまとめてコピーできます。
どちらもコピーに成功すると完了状態を表示し、2秒後に元の表示へ戻ります。デモでは実際に文字や文章を入力してコピー操作を試せるほか、入力した値・変数の内容・データ型を確認できます。なお、クリップボードへのコピー機能はHTTPSまたはlocalhostなどの安全な環境で利用できます。
デモ
①は入力欄の右端にあるコピーアイコン、②は入力欄の下にある「コピー」を押すと、入力内容をクリップボードへコピーできます。①はコピー成功時にチェックアイコンへ切り替わり、②は「コピーしました」と表示されます。どちらも2秒後に元の表示へ戻り、入力内容は消えません。コピー機能はHTTPSまたはlocalhostなどの安全な環境で利用してください。
Q 他のアイコンを使いたい場合はどうするの?
無料のSVGアイコン作成ツールを使って、用途に合ったアイコンを作成できます。
コードをコピーして使おう!
① 1行入力(テキストフィールド)
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コードの設定 -->
<meta charset="UTF-8">
<!-- スマートフォンなどの画面幅に対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ページタイトル -->
<title>コピーボタン付きテキストフィールド</title>
<!-- テキストフィールドのCSSを読み込む -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- テキストフィールド全体の横幅を制御する親要素 -->
<div class="textarea-copy-button_container">
<!-- 入力欄のラベル -->
<label class="textarea-copy-button_label" for="textarea-copy-button-first">
お名前
</label>
<!-- 入力欄とコピーアイコンを重ねて配置する要素 -->
<div class="textarea-copy-button_input-wrap">
<!-- コピー対象のテキストフィールド。idをJavaScriptから参照します -->
<input class="textarea-copy-button_input" id="textarea-copy-button-first" name="name" type="text" placeholder="お名前を入力してください">
<!-- 入力内容をコピーするボタン。data-copy-targetには入力欄のidを指定します -->
<button class="textarea-copy-button_copy-inline" type="button" data-copy-target="textarea-copy-button-first" aria-label="入力内容をコピー">
<!-- 通常時に表示するコピーアイコン -->
<svg class="textarea-copy-button_icon-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<rect x="8" y="3" width="13" height="15" rx="1"></rect>
<path d="M16 21H5a2 2 0 0 1-2-2V7"></path>
</svg>
<!-- コピー成功時に表示するチェックアイコン -->
<svg class="textarea-copy-button_icon-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="m5 12 5 5L20 7"></path>
</svg>
</button>
</div>
</div>
<!-- コピーボタンのJavaScriptを読み込む -->
<script src="script.js"></script>
</body>
</html>
② 複数行入力(テキストエリア)
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コードの設定 -->
<meta charset="UTF-8">
<!-- スマートフォンなどの画面幅に対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ページタイトル -->
<title>コピーボタン付きテキストエリア</title>
<!-- テキストエリアのCSSを読み込む -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- テキストエリア全体の横幅を制御する親要素 -->
<div class="textarea-copy-button_container">
<!-- 入力欄のラベル -->
<label class="textarea-copy-button_label" for="textarea-copy-button-second">
お問い合わせ内容
</label>
<!-- コピー対象のテキストエリア。idをJavaScriptから参照します -->
<textarea class="textarea-copy-button_textarea" id="textarea-copy-button-second" name="message" placeholder="お問い合わせ内容を入力してください"></textarea>
<!-- コピーボタンを右側に配置する要素 -->
<div class="textarea-copy-button_actions">
<!-- data-copy-targetにはコピー対象のテキストエリアのidを指定します -->
<button class="textarea-copy-button_copy" type="button" data-copy-target="textarea-copy-button-second">
コピー
</button>
</div>
</div>
<!-- コピーボタンのJavaScriptを読み込む -->
<script src="script.js"></script>
</body>
</html>
コードをコピーする場合 使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。 サンプル一式を取得する場合 HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
Q ダウンロードしたけど、これをネット上で動かすにはどうするの?
Googleアカウントがあれば、InfinityFreeで無料サーバーを作成して、ダウンロードしたサンプルをネット上で動かせます。
InfinityFreeを初めて利用する場合は①から、すでにサーバーを作成している場合は②へ進んでください。
ファイル構成と設置方法
今回のサンプルは、HTML・CSS・JavaScriptの3つのファイルで構成されています。1行入力のテキストフィールドと複数行入力のテキストエリアは、それぞれ独立したサンプルとしてダウンロードできます。どちらも入力内容をクリップボードへコピーする仕組みですが、ボタンの配置とコピー完了時の表示が異なります。
2種類のサンプルは、どちらも次のファイル構成です。使用したいタイプの「サンプル一式をダウンロード」から、それぞれのZIPファイルを保存してください。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlには、入力欄・ラベル・コピーボタンを記述しています。テキストフィールド版にはコピー用とチェック用のSVGアイコンが含まれ、テキストエリア版には文字で状態を知らせるボタンが含まれています。
style.cssでは、入力欄の横幅・余白・枠線・角丸・ボタンの配置などを設定しています。テキストフィールド版では、SVGアイコンの切り替えアニメーションも指定しています。
script.jsでは、入力された文字列の取得、クリップボードへのコピー、コピー完了時の表示切り替え、元の表示へ戻す処理を行っています。
設置方法・使い方
使用したいタイプのZIPファイルをダウンロードして展開し、sampleフォルダ内の3つのファイルを同じ階層に配置してください。コピー機能を使用するには、HTTPSに対応したWebサーバー、またはlocalhostなどの安全な環境でindex.htmlを開きます。
テキストフィールド版では、名前を入力して右端のコピーアイコンをクリックします。コピーに成功するとチェックアイコンへ切り替わり、2秒後に元のアイコンへ戻ります。
テキストエリア版では、文章を入力して下の「コピー」ボタンをクリックします。改行を含む文章もまとめてコピーでき、成功するとボタンに「コピーしました」と表示されます。こちらも2秒後に「コピー」へ戻ります。
入力欄とコピーボタンを関連付ける方法
コピーボタンには、コピー対象の入力欄を指定するdata-copy-target属性を設定しています。テキストフィールド版では、次のHTMLを使用しています。
<!-- コピー対象のテキストフィールド。idをJavaScriptから参照します -->
<input class="textarea-copy-button_input" id="textarea-copy-button-first" name="name" type="text" placeholder="お名前を入力してください">
入力欄にはid="textarea-copy-button-first"が設定されています。コピーボタンでは、次のように同じIDを指定しています。
<!-- 入力内容をコピーするボタン。data-copy-targetには入力欄のidを指定します -->
<button class="textarea-copy-button_copy-inline" type="button" data-copy-target="textarea-copy-button-first" aria-label="入力内容をコピー">
data-copy-targetの値と入力欄のidを一致させることで、JavaScriptがコピー対象を特定できます。入力欄のIDを変更する場合は、ボタン側のdata-copy-targetも同じ値に変更してください。
テキストエリア版でも仕組みは同じです。入力欄のIDにはtextarea-copy-button-secondを使用しています。
入力した文字列を取得してコピーする仕組み
script.jsでは、ボタンに設定されたdata-copy-targetを読み取り、対応する入力欄から文字列を取得しています。テキストフィールド版とテキストエリア版では、次の処理を共通して使用しています。
// data-copy-targetで指定された入力欄を取得
const input = document.getElementById(button.dataset.copyTarget);
// 対象の入力欄が存在しない場合は処理を終了
if (!input) return;
// 入力された文字列を取得
const value = input.value;
// 前回のタイマーを解除
clearTimeout(resetTimer);
try {
// 入力内容をクリップボードへコピー
await navigator.clipboard.writeText(value);
document.getElementById()でコピー対象の入力欄を取得し、input.valueで入力された文字列を変数valueへ代入しています。
navigator.clipboard.writeText(value)は、その文字列をクリップボードへコピーする処理です。テキストエリアの場合もvalueで取得するため、文章中の改行を含めてコピーできます。
コピーに失敗した場合は、テキストフィールド版ではボタンの説明を「コピーに失敗しました」に変更し、テキストエリア版ではボタンに「コピー失敗」と表示します。
入力した値を取得する方法
コピー処理とは別に、入力した値をJavaScriptの変数へ取得することもできます。テキストフィールド版では、次のコードを使用します。
以下は値の取得方法を説明するための追加例であり、ダウンロードするZIPには含まれていません。
// テキストフィールドの要素を取得
const input = document.getElementById("textarea-copy-button-first");
// 入力された文字列を変数へ代入
const value = input.value;
valueには、取得した時点でテキストフィールドに入力されている文字列が入ります。例えば「山田太郎」と入力されている場合は、変数valueに"山田太郎"が代入されます。
テキストエリア版では、取得する要素のIDを変更します。
// テキストエリアの要素を取得
const input = document.getElementById("textarea-copy-button-second");
// 改行を含む入力内容を変数へ代入
const value = input.value;
テキストエリアで入力した文章も文字列として取得できます。改行を含む場合は、その改行も文字列に含まれます。
これらのコードは実行した時点の値を取得します。取得した値は、コピー以外のJavaScriptの処理にも利用できます。
SVGアイコンの切り替えと変更方法
テキストフィールド版のコピーボタンには、通常時のコピーアイコンと、コピー成功時のチェックアイコンを重ねて配置しています。JavaScriptがコピーに成功すると、ボタンへis-copiedクラスを追加します。
style.cssでは、このクラスの有無によって2つのSVGアイコンの表示を切り替えています。
/* 通常時はコピーアイコンを表示 */
.textarea-copy-button_copy-inline .textarea-copy-button_icon-copy {
opacity: 1; /* コピーアイコンを表示する */
transform: scale(1); /* 元の大きさで表示する */
}
/* 通常時はチェックアイコンを非表示 */
.textarea-copy-button_copy-inline .textarea-copy-button_icon-check {
opacity: 0; /* チェックアイコンを透明にする */
transform: scale(0.7); /* 元の大きさの70%に縮小する */
}
/* コピー成功時はコピーアイコンを非表示 */
.textarea-copy-button_copy-inline.is-copied .textarea-copy-button_icon-copy {
opacity: 0; /* コピーアイコンを透明にする */
transform: scale(0.7); /* 元の大きさの70%に縮小する */
}
/* コピー成功時はチェックアイコンを表示 */
.textarea-copy-button_copy-inline.is-copied .textarea-copy-button_icon-check {
opacity: 1; /* チェックアイコンを表示する */
transform: scale(1); /* 元の大きさに拡大する */
}
opacityで透明度を、transform: scale()でアイコンの大きさを変更しています。通常時はコピーアイコンが表示され、コピー成功時にはチェックアイコンが拡大しながら表示されます。
アイコンの切り替え時間は、次のCSSで設定しています。
/* =========================================
SVGアイコンのサイズと切り替えアニメーション
========================================= */
.textarea-copy-button_copy-inline svg {
position: absolute; /* 2種類のアイコンを同じ位置に重ねる */
width: 20px; /* SVGアイコンの横幅 */
height: 20px; /* SVGアイコンの高さ */
transition: opacity 0.5s ease, transform 0.5s ease; /* 0.5秒かけて透明度と大きさを滑らかに切り替える */
}
widthとheightを変更すると、SVGアイコンの表示サイズを調整できます。transitionの0.5sを大きくすると切り替えがゆっくりになり、小さくすると速くなります。
別のアイコンを使用したい場合は、index.htmlに記述されているコピー用またはチェック用の<svg>~</svg>全体を、使用したいSVGコードへ置き換えてください。
コピー完了後に元の表示へ戻す仕組み
テキストフィールド版では、コピー成功時にis-copiedクラスを追加し、ボタンの説明を変更しています。
// コピー成功時はチェックアイコンへ切り替える
button.classList.add("is-copied");
// コピー成功をボタンの説明に反映する
button.setAttribute("aria-label", "コピーしました");
その後、setTimeout()を使って2秒後に通常のコピーアイコンへ戻しています。
// 2000ミリ秒(2秒)後に元のアイコンへ戻す
resetTimer = setTimeout(function() {
// チェックアイコンからコピーアイコンへ戻す
button.classList.remove("is-copied");
// ボタンの説明を元に戻す
button.setAttribute("aria-label", "入力内容をコピー");
}, 2000);
2000はミリ秒単位の待機時間です。例えば3000に変更すると、3秒後に元の表示へ戻ります。コピー操作を繰り返した場合は、前回のタイマーを解除してから新しいタイマーを設定します。
テキストエリア版では、SVGアイコンを使用せず、コピー成功時にボタンの文字を変更しています。
// コピー成功時はボタンの文字を変更する
button.textContent = "コピーしました";
テキストエリア版でも2秒後に元の表示へ戻ります。表示する文字を変更したい場合は、script.jsのbutton.textContentに指定した文字列と、index.htmlのボタン内の文字を編集してください。
レスポンシブ対応
両方のサンプルでは、.textarea-copy-button_containerにwidth: 100%;とmax-width: 480px;を設定しています。設置先の横幅に合わせて縮小しながら、最大横幅を480pxに制限しています。
さらに、画面幅が640px以下の場合は、入力欄の内側の余白を調整します。テキストフィールド版では、次のCSSを使用しています。
/* =========================================
スマートフォン対応
========================================= */
@media (max-width: 640px) {
/* 画面幅640px以下のテキストフィールド */
.textarea-copy-button_input {
padding: 14px; /* 上下左右の基本余白を14pxに変更する */
padding-right: 56px; /* コピーアイコン用の右余白を維持する */
}
}
テキストフィールド版では、画面幅が640px以下になると基本余白を16pxから14pxへ変更します。右側は56pxの余白を維持し、入力文字とコピーアイコンが重ならないようにしています。
テキストエリア版では、画面幅640px以下で内側の余白を14pxに変更しています。どちらもmax-widthやpaddingの値を変更することで、設置先の横幅やスマートフォンでの表示に合わせて調整できます。
コメント