Declarative Shadow DOM
Using shadow DOM previously required JavaScript:
this.attachShadow({mode: "open"});
You can now utilise shadow DOM entirely in HTML by using the shadowrootmode
attribute on a <template>
element.
<div>
<template shadowrootmode="open">
<p>This is in the shadow DOM</p>
<button>Shadow button</button>
</template>
</div>
While Shadow DOM is typically used together with custom elements, you can attach Shadow DOM to most HTML elements.
Any elements within the <template>
will be in the shadow DOM. You can optionally use the <slot>
element to render content within the light DOM.
<div>
<template shadowrootmode="open">
<p>This is in the shadow DOM</p>
<slot>
<p>This is in the light DOM</p>
<button>Light button</button>
</slot>
<button>Shadow button</button>
</template>
</div>
Any elements that are outside of the template, but within the parent of the template (a div
in this example) will end up in the <slot>
.
<div>
<template shadowrootmode="open">
<p>This is in the shadow DOM</p>
<slot></slot>
<button>Shadow button</button>
</template>
<p>This ends up in the slot</p>
<button>This also ends up in the slot</button>
</div>
You can use a <style>
tag to style the contents of the shadow DOM:
<div>
<template shadowrootmode="open">
<style>
p {
color: red;
}
button {
background-color: blue;
}
</style>
<p>This is in the shadow DOM</p>
<button>Shadow button</button>
</template>
</div>
React problems
If you try to use declarative shadow DOM in a React component, you’ll run into problems:
export default function Thing() {
return (
<div>
<template shadowrootmode="open">
<h2>This is in the shadow DOM</h2>
</template>
</div>
);
}
In Next.js, you’ll get the error “Error: Hydration failed because the initial UI does not match what was rendered on the server. Warning: Expected server HTML to contain a matching <template>
in <div>
.” In Remix the shadow DOM will momentarily render before disappearing, but doesn’t log any kind of error.
Somebody raised an issue in the React GitHub repo but I would very much doubt it will be fixed anytime soon, if ever.