The HTML shadowrootclonable attribute
The HTML shadowrootclonable attribute lets a declarative shadow root be copied along with its host. With it, cloneNode() or document.importNode() on the host copies the shadow root too. Without it, a cloned host arrives with no shadow tree at all.
Overview
The shadowrootclonable attribute lets a declarative shadow root survive cloning. It is a boolean attribute on a <template> with shadowrootmode, and it sets the created shadow root's clonable flag to true.
Cloning normally skips shadow trees. The DOM Standard copies a host's shadow root only when that root is clonable, and then it attaches a new shadow root to the copy with the same mode, focus delegation and serializable setting and clones the children into it. A host without the flag produces a copy whose shadowRoot is null.
The shadow root comes along even for a shallow cloneNode() call. The deep flag only decides whether the host's light DOM children are cloned, and the template is not one of them, because the parser turns it into the shadow root instead of inserting it.
The flag also matters when you copy <template> contents that contain declarative shadow roots, because document.importNode() keeps only the clonable ones. Support arrived in Chrome and Edge 124, Firefox 125 and Safari 17.5, according to MDN's compatibility data.
Syntax
<div>
<template shadowrootmode="open" shadowrootclonable>
<p>Copied along with the host</p>
</template>
</div>
Values
| Value |
|---|
| A boolean attribute: present or absent. |
Example
<div id="a"><template shadowrootmode="open" shadowrootclonable><b>Clonable shadow content</b></template></div>
<div id="b"><template shadowrootmode="open"><b>Plain shadow content</b></template></div>
<p>Clones:</p>
<div id="copies"></div>
<p id="out"></p>
<script>
const copyA = document.getElementById('a').cloneNode(true);
const copyB = document.getElementById('b').cloneNode(true);
document.getElementById('copies').append(copyA, copyB);
document.getElementById('out').textContent =
'Clone of #a has a shadow root: ' + (copyA.shadowRoot !== null) + ', clone of #b: ' + (copyB.shadowRoot !== null);
</script>
Best practices
- Add
shadowrootclonableto declarative components that you duplicate withcloneNode()orimportNode(), such as rows built from a template. - Check
host.shadowRoot.clonableon an open shadow root when a copy renders empty, since false means the shadow tree was never copied. - For shadow roots created in script, pass
clonable: truetoattachShadow(), because the template attribute only covers declarative roots. - Remember that a clone gets an independent copy of the shadow tree, so later changes to the original's shadow content do not carry over.
Frequently asked questions
What does shadowrootclonable do?
Why does cloneNode() lose my shadow DOM?
clonable: true to attachShadow().






















