Simplify Shadow DOM with setHTMLUnsafe
JS Bits Bill
Posted on May 3, 2024
It's typical for Web developers to create encapsulated DOM elements in order to isolate both styles and functionality within a component. To achieve this, the element.attachShadow
method is used to create a shadow DOM: a hidden subtree attached to an element. While powerful, it can be somewhat verbose and complex to set up:
const sectionElement = document.querySelector('section');
const shadowTemplate = document.createElement('template');
shadowTemplate.innerHTML = `
<style>
/* Shadow styles applied only within the shadow DOM */
h2 { color: blue; }
</style>
<h2>Shadow Content</h2>
`;
shadowTemplate.content.shadowRootMode = 'open'
const shadowHost = document.createElement('div');
const shadowRoot = shadowHost.attachShadow({
mode: 'open'
});
shadowRoot.appendChild(shadowTemplate.content.cloneNode(true));
sectionElement.appendChild(shadowHost);
sectionElement.insertAdjacentHTML('beforeend', `
<h2>Light Content</h2>
`);
This produces the following rendered HTML:
Notice how we must create the shadow DOM using the .attachShadow
method first and then we can access the shadow root and use .innerHTML
to populate the content.
Also note how .innerHTML
cannot be used to directly create this output. This method is not designed to understand shadow elements within the template. Further, it also prevents this content from rendering due to a browser security restriction. If user-generated content is inserted with .innerHTML
, it could contain malicious scripts that execute within your page. Shadow DOM creates a separate DOM tree that prevents styles and scripts from leaking into the main page.
However, if we understand and accept the security implications, we can take advantage of the new setHTMLUnsafe
method to directly set HTML content, including shadow DOM declarations, bypassing the need for separate shadow DOM attachment methods like .attachShadow
:
document.querySelector('section').setHTMLUnsafe(`
<div>
<template shadowrootmode="open">
<style>
/* Shadow styles applied only within the shadow DOM */
h2 { color: blue; }
</style>
<h2>Shadow Content</h2>
</template>
</div>
<h2>Light Content</h2>
`)
With setHTMLUnsafe
, you don't need to manage separate template elements, shadow hosts, or shadow roots manually. This can reduce the complexity of your codebase and make it easier to maintain, especially in larger projects where encapsulation of DOM elements is a common practice.
setHTMLUnsafe
is available now in Chrome 124 (and supported in Edge, Safari, and Firefox).
Posted on May 3, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024