Declarative Shadow DOM
Attach shadow DOM from HTML without JavaScript using shadowrootmode.
Declarative Shadow DOM is a free HTML Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Problem It Solves
Traditional Shadow DOM is created via JavaScript (attachShadow). For server-rendered pages, this means the shadow tree is empty until JS runs — defeating SSR's purpose of delivering complete HTML on first byte. Declarative Shadow DOM fixes this.
The shadowrootmode Attribute
A <template> with shadowrootmode="open" declares a shadow root in HTML at parse time. The browser attaches the shadow root to the parent element automatically; the template's content becomes the shadow tree. No JavaScript required.
<my-card>
<template shadowrootmode="open">
<style>:host { display: block; padding: 16px; }</style>
<slot></slot>
</template>
<p>This goes into the slot</p>
</my-card>SSR With Web Components
Declarative Shadow DOM enables true server-rendered web components: the server emits the full shadow tree inline, the browser parses and attaches it before any JS executes, and hydration JS can take over from a fully-rendered baseline. Equal footing with framework SSR.
Mode: open or closed
Same modes as imperative attachShadow: shadowrootmode="open" exposes the shadow as element.shadowRoot; shadowrootmode="closed" hides it. Behavior is identical to the JavaScript-attached counterpart.
Parsed Once Per Element
The browser attaches the shadow root the first time it sees the <template shadowrootmode>. Once attached, the template is consumed — querying for it later returns nothing. This matches the lifecycle of attachShadow: a shadow exists for the life of the element.
Slots Work Normally
Light children (the <p> outside the <template> in the example) project into <slot> elements inside the shadow tree, just as with imperative shadow DOM. The composition story is identical; only the attachment mechanism differs.
Combining With Custom Elements
If <my-card> is a registered custom element, the upgrade process picks up the already-attached shadow root rather than calling attachShadow again. The custom element class can read this.shadowRoot in its connectedCallback without needing to create it.
Server Tooling Support
Lit-html's render, Astro components, and several other frameworks now emit declarative shadow DOM as part of their SSR output. Roll-your-own is feasible: any string-templating system can write the shadowrootmode template.
Browser Support
Declarative Shadow DOM ships in Chrome, Edge, Safari and Firefox. Older browsers ignore the <template> element silently — content inside the template is invisible, which is graceful degradation for non-supporting environments.
Polyfill Strategy
For broader support, a small script can walk the DOM and convert template[shadowrootmode] into actual shadow roots. Run before any custom element registration to ensure subsequent component upgrades see the expected shadow tree.
Trade-Offs
Declarative shadow DOM duplicates structure: the <template> content lives in the HTML even though it is also baked into the component's class. For pages with many of the same component, this inflates payload. Frameworks deduplicate; hand-rolled SSR may want to do the same.
When to Adopt
If you ship web components and care about first-byte rendering or SEO — adopt now. The feature is stable, supported, and dramatically improves the SSR story for web-component-based applications. For non-shadow-DOM apps it does not apply.
Knowledge Check
What problem does Declarative Shadow DOM solve compared to imperative attachShadow?
Summary
Declarative Shadow DOM uses <template shadowrootmode="open"> inside a custom element to attach a shadow root at parse time, no JS required. Enables true SSR for web components: shadow tree, scoped styles, and slots all work before hydration. Supported in all modern browsers; polyfill available for older ones. Frameworks (Lit, Astro) emit it automatically.
Frequently asked questions
Is the “Declarative Shadow DOM” lesson free?
Yes — the full text of “Declarative Shadow DOM” is free to read here on the web, and the HTML Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the HTML Academy course, upgrade to CoddyKit PRO.
What will I learn in “Declarative Shadow DOM”?
Attach shadow DOM from HTML without JavaScript using shadowrootmode. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start HTML Academy?
No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Declarative Shadow DOM” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this HTML Academy lesson?
Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Declarative Shadow DOM
- The Popover API
- The selectlist Element
- Interest Invokers and Command Attribute