この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: 要素のコピー
SEOタイトル: jQuery で要素をコピーする方法(clone / clone(true) でイベント込み複製 / appendTo / 動的フォーム追加 / vanilla JS cloneNode との比較)

この記事の要点
  • jQuery で要素を複製するには $(selector).clone() を使う
  • clone()イベントハンドラやデータをコピーしないのが既定。コピーするには clone(true)
  • 複製後は appendTo() / prependTo() / before() / after() でどこに挿入するかを指定する
  • id 属性もそのまま複製されるため、ID 重複に注意 — 複製後に書き換えるかクラスベースに設計する
  • 純粋 JS なら Node.cloneNode(true)。SPA / モダン開発では vanilla JS で十分なケースも多い

jQuery clone() の基本

clone() は jQuery オブジェクトをディープコピーするメソッドです。元の要素を残したまま同じ HTML 構造を複製し、appendTo などで好きな場所に挿入できます。動的なフォーム追加、リスト項目の追加 UI などに頻出する基本機能です。

HTML

上記の をコピーする例です。

jQuery 実装


clone() でコピー、appendTo()#item_list の末尾に追加しています。これだけで「ボタンを押すたびに input が増える」ような動的フォームを実現できます。

clone() と clone(true) の違い

呼び方イベントハンドラdata()用途
clone()コピーしないコピーしないHTML 構造のみ複製
clone(true)コピーするコピーするイベント込みで複製
clone(true, true)コピー + 子孫もコピー + 子孫も完全な深いコピー
// 例: クリックイベント付きボタンを複製
$("#origBtn").on("click", function() {
  alert("クリックされた!");
});

$("#origBtn").clone().appendTo("body");
// コピー先のボタンを押しても何も起きない

$("#origBtn").clone(true).appendTo("body");
// コピー先のボタンも同じアラートが出る

挿入位置の指定

メソッド挿入位置
appendTo(parent)親の末尾(子要素として)
prependTo(parent)親の先頭
insertAfter(target)対象の直後(同階層)
insertBefore(target)対象の直前
$("#item").clone().insertAfter("#item");          // 同じ階層、直後
$("#card").clone().prependTo("#list");            // リスト先頭に
$("#row").clone().insertBefore("#footerRow");     // フッター行の前に

ID 重複の罠

HTML の id 属性はドキュメント内で一意であるべきですが、clone() は属性をそのまま複製するため同じ id を持つ要素が複数できてしまいます。

// NG: 2 つの #item ができてしまう
$("#item").clone().appendTo("#item_list");

// OK: id を書き換える
let count = $("#item_list input").length;
$("#item")
  .clone()
  .attr("id", "item_" + count)         // id を一意化
  .removeAttr("name")                  // 必要に応じて
  .val("")                             // 値クリア
  .appendTo("#item_list");

// よりベストプラクティス: ID ではなくクラスで設計
$(".item").first().clone().appendTo("#item_list");

動的フォーム追加の完全例

$(function() {
  // 行追加
  $("#addRow").on("click", function() {
    const $row = $("#form-rows .row").first().clone();
    $row.find("input").val("");      // 値をクリア
    $row.appendTo("#form-rows");
  });

  // 行削除(イベント委譲)
  $("#form-rows").on("click", ".remove", function() {
    if ($("#form-rows .row").length > 1) {
      $(this).closest(".row").remove();
    }
  });
});

イベント委譲(on("click", ".remove", ...))を使えば、後から追加された行の削除ボタンにも自動でイベントが効きます。これと clone() を組み合わせるのが動的フォームの王道パターン。

外す系メソッドとの関係

メソッド挙動
clone()元を残してコピー
detach()DOM から外すが内部のデータ / イベントは保持
remove()DOM から削除、データもクリア
empty()子要素のみ削除

純粋な JavaScript(vanilla)での書き方

jQuery を使わない場合、Node.cloneNode(true) で同等の処理ができます。モダンブラウザではこれで十分なケースも多い。

function copyItem() {
  const orig = document.getElementById("item");
  const copy = orig.cloneNode(true);   // true で子孫もコピー
  copy.removeAttribute("id");          // ID 重複回避
  copy.value = "";
  document.getElementById("item_list").appendChild(copy);
}
項目jQuery clonecloneNode
子孫も複製常に深い引数 true で深い
イベントもコピーclone(true) で可cloneNode は不可(手動で設定)
jQuery 依存ありなし(標準 DOM API)

パフォーマンスの注意

  • 巨大な DOM を頻繁に clone するとメモリと描画コストが大きい
  • 追加が大量にあるならDocumentFragment を使ってまとめて挿入(vanilla JS の場合)
  • 頻繁な DOM 追加削除は仮想 DOM フレームワーク(React / Vue)の方が効率的

FAQ

Q: clone() でイベントが効かない
A: 既定の clone() はイベントをコピーしません。clone(true) を使うか、イベント委譲($(parent).on("click", ".child", ...))で解決します。後者の方がメモリ効率が良いです。

Q: フォームの value がコピーされない
A: ブラウザによっては input の値属性と value プロパティが別扱い。コピー後に .val("") でクリアしたり、.val(orig.val()) で改めて設定するのが安全。

Q: jQuery を使わずに同じことをしたい
A: element.cloneNode(true) + parent.appendChild() で同等です。イベントは addEventListener で都度設定。

関連

  • jQuery — DOM 操作を簡潔にするライブラリ
  • appendTo / prependTo — 要素の追加
  • on — イベントハンドラの設定(委譲も対応)
  • cloneNode — 純粋 JS の DOM 複製 API
  • DocumentFragment — 一括挿入の高速化