jQuery .clone() Method

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
DOM methods

What You’ll Learn

The .clone() method creates a deep copy of matched elements (and their descendants). This tutorial covers basic cloning, cloning with event handlers and data, deep cloning of children’s events, modifying clones before insert, comparisons with move-vs-copy insertion, duplicate id pitfalls, five practical examples, and try-it labs.

01

.clone()

Deep copy

02

Events

.clone(true)

03

Deep

Children too

04

Modify

Then insert

05

vs move

appendTo

06

Since 1.0

Core API

Introduction

Apps often need a second copy of a card, list item, or form row — keep the template on the page and duplicate it when the user clicks “Add another.” jQuery’s .clone() builds that copy for you.

Available since jQuery 1.0, .clone() performs a deep copy: the matched elements plus all descendant elements and text nodes. By default, event handlers are not copied. Pass true to include handlers and (since 1.4) element data. Since 1.5, a second Boolean controls whether children also get events and data.

Cloning alone does not insert anything. Chain .appendTo(), .prependTo(), or .insertAfter() to place the copy. Without .clone(), those same methods move existing nodes. Browse the jQuery DOM hub for related methods.

Understanding the .clone() Method

.clone( [withDataAndEvents] [, deepWithDataAndEvents] ) returns a new jQuery collection containing copies of the matched set. The originals stay where they are. Descendants are always included in the structure copy.

The first Boolean (default false) copies event handlers and, since 1.4, data attached with .data(). The second Boolean (since 1.5) defaults to the same value as the first and applies that choice to all children.

💡
Beginner Tip

Think: $(".hello").appendTo(".goodbye") moves the hello block. $(".hello").clone().appendTo(".goodbye") copies it so both places show Hello — the classic official jQuery demo pattern.

⚠️
Duplicate IDs

Cloning copies the id attribute. HTML requires unique IDs. After .clone(), update the clone’s id (and related for / ARIA refs) before inserting, or avoid IDs on template elements you plan to duplicate.

📝 Syntax

jQuery .clone() supports two signatures:

Clone structure only — since 1.0

jQuery
.clone( [withDataAndEvents] )
  • withDataAndEvents (default false) — copy event handlers; since 1.4 also copy .data().

Clone with deep events/data — since 1.5

jQuery
.clone( [withDataAndEvents] [, deepWithDataAndEvents] )
  • deepWithDataAndEvents — copy events/data for all children; defaults to the first argument’s value.
  • Note: in jQuery 1.5.0 the first-argument default briefly was true; from 1.5.1 onward it is false again.

Return value

  • Returns a new jQuery collection of the cloned elements (not yet in the document unless you insert them).
  • Chain modifiers like .attr(), .text(), or .appendTo() on the clone.

Official clone patterns

jQuery
$( "b" ).clone().prependTo( "p" );
jQuery
$( ".hello" ).clone().appendTo( ".goodbye" );

⚡ Quick Reference

GoalCode
Copy structure only$(".card").clone()
Copy + insert$(".card").clone().appendTo("#list")
Copy with events & data$(".btn").clone(true)
Copy events on children too$(".widget").clone(true, true)
Modify before insert$("#tpl").clone().removeAttr("id").appendTo(box)
Deep-copy array in .data().data("arr", $.extend([], $orig.data("arr")))

📋 .clone() vs move vs .detach()

Three ways to work with existing nodes — copy, relocate, or stash.

.clone()
copy

Original stays; insert the returned copy with appendTo / after / prependTo

.appendTo()
move

Without clone, an in-document element is moved (not duplicated)

.detach()
stash

Remove from DOM but keep jQuery data/events for later reinsert

clone(true)
events

Also copy handlers and .data() — use for interactive templates

Examples Gallery

Examples follow the official jQuery API patterns and common production workflows. Use View Output or Try It Yourself to explore each case.

📚 Getting Started

Official-style demos for structural cloning and move-vs-copy.

Example 1 — Official Pattern: Clone and Prepend

Clone all <b> elements and prepend the copies into every paragraph.

jQuery
$( "b" ).clone().prependTo( "p" );
Try It Yourself

How It Works

.clone() builds detached copies. .prependTo("p") inserts each copy as the first child of every matched paragraph. Event handlers are not copied unless you pass true.

Example 2 — Clone vs Move With .appendTo()

Without .clone(), inserting an existing node moves it. With .clone(), both copies remain.

jQuery
// Moves .hello into .goodbye (original location empty)
$( ".hello" ).appendTo( ".goodbye" );

// Keeps original .hello and adds a copy inside .goodbye
$( ".hello" ).clone().appendTo( ".goodbye" );
Try It Yourself

How It Works

Insertion methods operate on the matched set. If those elements are already in the document, jQuery relocates them. Cloning first creates new nodes so insertion does not empty the original parent.

📈 Practical Patterns

Events, template editing, and deep cloning for nested widgets.

Example 3 — Clone With Event Handlers

Pass true so click handlers on the original also work on the copy.

jQuery
$( "#add" ).on( "click", function() {
  $( ".row" ).first()
    .clone( true )
    .find( "input" ).val( "" ).end()
    .appendTo( "#rows" );
});
Try It Yourself

How It Works

.clone(true) duplicates handlers bound with jQuery. Nested interactive children may still need .clone(true, true). Objects/arrays stored in .data() are shared by reference unless you deep-copy them manually with $.extend.

Example 4 — Modify the Clone Before Inserting

Change text, remove the template id, then append the prepared copy.

jQuery
var $copy = $( "#card-template" )
  .clone()
  .removeAttr( "id" )
  .removeClass( "is-template" )
  .find( "h3" ).text( "Cloned card" ).end();

$copy.appendTo( "#board" );
Try It Yourself

How It Works

The jQuery docs note you can modify clones before re-inserting. Use .find().end() to edit descendants then return to the root clone for .appendTo(). Always strip or rewrite IDs on templates.

Example 5 — Deep Clone Events on Children

Use two true arguments so nested buttons keep their handlers.

jQuery
// Copy widget + child button handlers/data
var $dup = $( "#widget" ).clone( true, true );
$dup.attr( "id", "widget-copy" ).appendTo( "#stage" );
Try It Yourself

How It Works

.clone(true) alone copies events on the matched root. Nested elements that were bound separately need .clone(true, true) (jQuery 1.5+). Prefer event delegation (.on("click", ".child", fn) on a parent) when many clones share the same behavior — then a plain .clone() is enough.

🚀 Common Use Cases

  • Dynamic form rows — clone a field group when the user adds another item.
  • Card / widget templates — keep a hidden template and clone it into a board.
  • List duplication — copy a selected item instead of rebuilding HTML strings.
  • Demo / preview panes — show a read-only clone of a live component.
  • Preserving interactivity.clone(true) or .clone(true, true) for widgets with handlers.
  • Safer than string HTML — clone existing trusted markup instead of concatenating HTML from data.

🧠 How .clone() Builds a Copy

1

Match source elements

Select the nodes you want to duplicate (and their descendants).

Select
2

Deep-copy the tree

Structure and text nodes are copied; optionally events and data too.

Clone
3

Optionally edit the copy

Change ids, text, classes, or clear inputs before insertion.

Modify
4

Insert into the document

Chain .appendTo(), .prependTo(), .after(), or similar.

📝 Notes

  • Available since jQuery 1.0; second parameter since 1.5; data copied with events since 1.4.
  • Always a deep structural copy of descendants — there is no “shallow element only” mode.
  • Default does not copy event handlers; use .clone(true) or .clone(true, true).
  • Objects and arrays in .data() are shared between original and clone unless you deep-copy them.
  • Duplicated id attributes are invalid HTML — rewrite or remove them on clones.
  • textarea typed values and select selections are not copied for performance; input dynamic state generally is.
  • Event delegation on a stable parent often beats deep-cloning handlers for repeating UI.

Browser Support

.clone() has been part of jQuery since 1.0+. The withDataAndEvents option dates to 1.0 (with data included since 1.4); deepWithDataAndEvents was added in 1.5+. Works in all browsers supported by your jQuery build — including modern evergreen browsers with jQuery 3.x and 4.x.

jQuery 1.0+

jQuery .clone()

Universal deep-copy API across jQuery 1.x–4.x. No browser-specific polyfills — jQuery normalizes cloning and optional event/data copying.

100% With jQuery loaded
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
.clone() Universal

Bottom line: Default choice for duplicating DOM subtrees before insertion.

Conclusion

The jQuery .clone() method deep-copies matched elements and their descendants. Chain an insertion method to place the copy, pass true (and optionally a second true) when events and data must travel with the duplicate, and always fix unique attributes like id before inserting.

Prefer event delegation when many identical clones share behavior. Next up: inserting matched elements after a target with .insertAfter().

💡 Best Practices

✅ Do

  • Use .clone() when you need a duplicate, not a move
  • Remove or rename id on clones before inserting
  • Use .clone(true) / .clone(true, true) when handlers must copy
  • Edit the clone (text, values, classes) before .appendTo()
  • Prefer delegated events on a parent for repeating rows

❌ Don’t

  • Expect .appendTo() alone to copy — it moves existing nodes
  • Leave duplicate IDs in the document after cloning
  • Assume textarea / select user state is copied
  • Share mutable .data() arrays/objects without deep-copying
  • Deep-clone events when simple event delegation would suffice

Key Takeaways

Knowledge Unlocked

Five things to remember about .clone()

The duplicate-then-insert API for DOM subtrees.

5
Core concepts
02

Not

A move

vs appendTo
03

Events

Optional

.clone(true)
# 04

Fix

IDs

Unique
05

Then

Insert

Chain

❓ Frequently Asked Questions

.clone() creates a deep copy of the matched elements, including all descendant elements and text nodes. The original stays in place. You usually chain an insertion method such as .appendTo() or .insertAfter() to put the copy into the document. Available since jQuery 1.0.
Appending (or .appendTo()) an element already in the document moves it to the new location. Calling .clone() first copies it, so the original remains and the copy is inserted. Use clone when you need duplicates.
By default, no. Pass true as the first argument — .clone(true) — to copy event handlers and (since 1.4) .data() values. As of 1.5, a second argument deepWithDataAndEvents controls whether children also get events and data copied.
The optional second Boolean (jQuery 1.5+) controls whether event handlers and data on all descendants of the cloned element are copied. By default it matches the first argument. Use .clone(true, true) to copy events/data on the element and its children.
Cloning copies attributes, including id. IDs must be unique in a document. After cloning, change the clone’s id (and any label[for] / aria references) before inserting, or prefer class-based selectors for elements you plan to duplicate.
For input elements, the dynamic state (typed text, checkbox selection) is generally retained on clones. For performance reasons, user data typed into textarea and selections on select are not copied to the clone — re-apply those values if needed.
Did you know?

.clone() has been in jQuery since version 1.0. The ability to copy events arrived early; copying .data() alongside events landed in 1.4, and deep child event/data copying arrived in 1.5. In 1.5.0 the default for withDataAndEvents briefly flipped to true before returning to false in 1.5.1 — always pass an explicit Boolean in production code for clarity.

Next: jQuery .insertAfter() Method

Insert matched elements after a target as siblings with content-first syntax.

.insertAfter() tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful