The JavaScript cloneNode() method
The cloneNode() method creates a copy of a DOM element. el.cloneNode(true) makes a deep copy including all descendants; el.cloneNode(false) copies only the element itself. The clone is detached, so insert it with appendChild() or append(). Event listeners are not copied.
Overview
cloneNode() duplicates an element. The single argument decides how much: cloneNode(true) is a deep clone that copies the element and everything inside it (the usual choice), while cloneNode(false) is a shallow clone that copies just the element with no children. Either way you get a brand-new, detached node.
This pairs naturally with appendChild(), which moves an existing node rather than copying it — so when you want a real duplicate (a new row, card or list item modeled on an existing one), you cloneNode(true) first, then insert the clone. A clean version of this is the <template> element: keep a hidden template, clone its content, fill it in, and append — the standard pattern for rendering repeated items without string-based HTML.
The big caveat: event listeners are not cloned. A clone has the same markup, attributes and inline handlers, but any listeners you added with addEventListener() do not carry over — you must re-attach them, or (better) use event delegation on a parent so the clone is covered automatically. IDs are copied too, so deep-cloning something with an id can create invalid duplicate IDs; update them after cloning.
Syntax
const deep = element.cloneNode(true); // element + all descendants
const shallow = element.cloneNode(false); // element only
const copy = original.cloneNode(true);
container.appendChild(copy); // insert the clone
Parameters
The cloneNode() method accepts the following parameters.
| Parameter | Description |
|---|---|
deep |
If true, copies the element and all its descendants (deep clone). If false (default), copies only the element. |
Example
<ul id="list" style="font:15px system-ui">
<li class="row">Template row</li>
</ul>
<button onclick="addRow()" style="font:14px system-ui;margin-top:8px">Clone a row</button>
<script>
let n = 1;
function addRow() {
const list = document.getElementById('list');
const copy = list.querySelector('.row').cloneNode(true);
copy.textContent = 'Cloned row ' + (++n);
list.appendChild(copy);
}
</script>
Best practices
- Use
cloneNode(true)for a full copy including children — the common case. - Re-attach event listeners after cloning, or use delegation on a parent so clones are covered.
- Update or remove the
idon a clone to avoid duplicate IDs. - For repeated UI, clone a hidden
<template>'s content, fill it, then append.
Frequently asked questions
What is the difference between cloneNode(true) and cloneNode(false)?
cloneNode(true) deep-clones the element and all its descendants; cloneNode(false) copies only the element with no children.Why don't my event listeners work on a cloned element?
cloneNode(). Re-attach them, or use event delegation on a parent.How do I duplicate an element on the page?
const copy = el.cloneNode(true); parent.appendChild(copy);.Does cloneNode() copy the id?
id — which can create invalid duplicate IDs. Change the clone's id after cloning.