rmcclellan is correct that you cannot "remove" ShadowRoot v2. But you can fake it.
OuterHTML Partial Solution
elementWithShadowDOMv2.outerHTML = elementWithShadowDOMv2.outerHTML;
HOWEVER, there is a serious warning: although there are no visual changes, elementWithShadowDOMv2 still refers to the destroyed element with ShadowDOMv2, as if elementWithShadowDOMv2.parentNode.removeChild( elementWithShadowDOMv2 ) was called. It also removes event listeners in the element. Check out the demo below.
var addShadowHere = document.getElementById("add-shadow-here"); addShadowHere.addEventListener("mouseenter", function() { addShadowHere.style.border = '2em solid blue'; }); addShadowHere.addEventListener("mouseleave", function() { addShadowHere.style.border = ''; }); var shadow = addShadowHere.attachShadow({mode:"open"}); var button = shadow.appendChild(document.createElement("button")); button.textContent = "Click Here to Destroy The ShadowDOMv2"; button.addEventListener("click", function() { addShadowHere.outerHTML = addShadowHere.outerHTML; update(); }); update(); function update() {
<div id="add-shadow-here">Text Hidden By Shadow DOM</div> addShadowHere.parentNode => <input readonly="" id="parent-value" />
Notice how the blue frame stops working after removing the ShadowDOM. This is because event listeners are no longer registered in the new element: event listeners remain registered in the old element, which is now removed from the DOM.
Thus, you must update any links to the element and reconnect any event listeners. Here is an example of how you can get a link to a new item.
function removeShadowWithCaveat(elementWithShadow) { if (!elementWithShadow.parentNode) return elementWithShadow.cloneNode(true); var parent = elementWithShadow.parentNode; var prior = elementWithShadow.previousSibling; elementWithShadow.outerHTML = elementWithShadow.outerHTML; return prior.nextSibling || parent.firstChild; }
If you need access to elements that are naturally hidden by the existing shadow root and which will become available after removing the shadow root, then there is an alternative method that will save these nodes perfectly.
function removeShadowWithCaveat(elementWithShadow) { if (!elementWithShadow.parentNode) return elementWithShadow.cloneNode(true); var ref = elementWithShadow.cloneNode(true); while (elementWithShadow.lastChild) ref.appendChild( elementWithShadow.lastChild ); elementWithShadow.parentNode.replaceChild(elementWithShadow, elementWithShadow); return ref; }
Working solution
var createShadowProp = ( "createShadowRoot" in Element.prototype ? "createShadowRoot" : "webkitCreateShadowRoot" ); function removeChildren(elt) { console.log('removing children: %s', elt); while (elt.firstChild) { elt.removeChild(elt.firstChild); } } function removeShadowWithCaveat(elementWithShadow) { if (!elementWithShadow.parentNode) return elementWithShadow.cloneNode(true); var ref = elementWithShadow.cloneNode(true); while (elementWithShadow.lastChild) ref.appendChild( elementWithShadow.lastChild ); elementWithShadow.parentNode.replaceChild(elementWithShadow, elementWithShadow); return ref; } function showPlainOldDiv() { console.log('adding a plain old div'); var host = document.querySelector('#content'); removeChildren(host);
<div> <input type="button" value="show plain old div" onclick="showPlainOldDiv()"/> <input type="button" value="show shadowed template" onclick="showShadowTemplate()"/> <div id="content"></div> </div> <template id="shadowedTemplateComponent" style="display:none"> <style> div { background: lightgray; } #t { color: red; } </style> <div id="t">template</div> <script>console.log("Activated the shadowed template component.");</script> </template> <template id="plainDiv" style="display:none"> <div id="plaindiv">Plain old div</div> </template>
Also, pay attention to the misuse of vendor prefixes (a problem that too many developers face). You are right that at the time this question was asked, there was only a prefix version of createShadowRoot (which was webkitCreateShadowRoot ). However, you should ALWAYS check if a non-fixed version of createShadowRoot is available if browsers standardize the API in the future (which is the case now). It might be nice for your code to work today, but it's great that your code works after a few years.
source share