DEV Community

Cover image for Web Components & Declarative Shadow DOM: A New Era for Reusable UI
martin rojas
martin rojas

Posted on

Web Components & Declarative Shadow DOM: A New Era for Reusable UI

Web components have been around for a while, but one of their biggest challenges has been server-side rendering (SSR). Traditionally, rendering web components required JavaScript to instantiate their Shadow DOM, which meant content wouldn’t appear until JavaScript ran—a major problem for performance, SEO, and accessibility.

Now, with Declarative Shadow DOM, developers can define Shadow DOM directly in HTML—allowing web components to be server-rendered, indexed by search engines, and usable even before JavaScript loads.

In this post, we’ll explore:

✅ How Web Components improve UI development.

✅ The limitations of traditional Shadow DOM and why SSR was difficult.

✅ How Declarative Shadow DOM solves this problem with real-world examples.

✅ Practical use cases and adoption strategies for developers.

Let’s dive in! 🚀


What Are Web Components?

Web Components are a set of browser-native technologies that let developers create custom, reusable HTML elements without relying on JavaScript frameworks.

Key Features of Web Components

1️⃣ Custom Elements – Define your own HTML tags (<my-button>, <user-card>, etc.).

2️⃣ Shadow DOM – Encapsulate styles and structure so they don’t leak into the rest of the page.

3️⃣ HTML Templates – Create reusable templates inside <template> tags.

4️⃣ Built-in Reusability – Work across different projects without a framework like React or Vue.

Example of a Simple Web Component

class MyButton extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `<button>Click me</button>`;
  }
}

customElements.define("my-button", MyButton);
Enter fullscreen mode Exit fullscreen mode
<my-button></my-button>
Enter fullscreen mode Exit fullscreen mode

Encapsulation: The button inside <my-button> is isolated from the rest of the page.

Reusability: You can use <my-button> anywhere without affecting global styles.


The Problem: Shadow DOM and Server-Side Rendering

One major drawback of Web Components has been SSR (Server-Side Rendering).

Before Declarative Shadow DOM:

  • Web components were invisible to search engines because their content was rendered dynamically with JavaScript.
  • Users would experience flash-of-unstyled-content (FOUC) while waiting for JavaScript to load.
  • No SEO-friendly indexing, since search engines couldn’t see inside Shadow DOM.

The Solution: Declarative Shadow DOM (DSD)

Declarative Shadow DOM allows Shadow DOM to be defined in raw HTML, instead of requiring JavaScript.

🔹 Before (JavaScript-based Shadow DOM):

const shadowRoot = myElement.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `<p>Hello, World!</p>`;
Enter fullscreen mode Exit fullscreen mode

🔹 Now (Declarative Shadow DOM in HTML):

<my-element>
  <template shadowroot="open">
    <p>Hello, World!</p>
  </template>
</my-element>
Enter fullscreen mode Exit fullscreen mode

No JavaScript required—content renders instantly.

Search engines can now index Web Component content.

Works with Server-Side Rendering (SSR), improving performance.

How Does It Work?

When the browser encounters a <template shadowroot="open">, it automatically attaches it to the parent element—just like JavaScript’s attachShadow(), but without requiring JavaScript execution.

This means web pages using Web Components can now:

Be rendered on the server before JavaScript loads.

Appear correctly in search engine crawlers (huge for SEO).

Improve first-contentful-paint (FCP) times for better performance.


Example: A User Profile Card with Declarative Shadow DOM

Here’s how you can create a reusable profile card using Declarative Shadow DOM:

<user-card>
  <template shadowroot="open">
    <style>
      .card {
        border: 1px solid #ddd;
        padding: 10px;
        border-radius: 5px;
      }
    </style>
    <div class="card">
      <h2>John Doe</h2>
      <p>Web Developer</p>
    </div>
  </template>
</user-card>
Enter fullscreen mode Exit fullscreen mode

Why This is Powerful:

No JavaScript needed—The component works instantly in the browser.

Pre-rendered on the server—Great for SEO and performance.

Scoped styles—The .card styles won’t leak into the rest of the page.


When to Use Declarative Shadow DOM

Declarative Shadow DOM is most useful when:

✔️ You need SEO-friendly Web Components (like product listings, blog cards, etc.).

✔️ Your app requires SSR (Next.js, Astro, etc.), but still wants the benefits of Web Components.

✔️ You want faster page loads by rendering Web Components before JavaScript loads.

✔️ You need encapsulated styles without affecting global styles.

When NOT to Use It

❌ If your Web Component logic relies heavily on JavaScript (e.g., event listeners, state changes).

❌ If you don’t need SEO or SSR benefits.


Browser Support & Adoption

🚀 Declarative Shadow DOM is supported in:

✅ Chrome 90+

✅ Edge (Chromium-based)

Not yet supported in Firefox or Safari (but polyfills exist).

Since it’s an opt-in feature, browsers that don’t support it will simply ignore it, making it safe to use with fallbacks.


Final Thoughts: The Future of Web Components & SSR

Declarative Shadow DOM is a game-changer for Web Components, finally making them SEO-friendly and server-renderable without JavaScript hacks.

Key Takeaways:

Web Components provide reusable, framework-agnostic UI elements.

Traditional Shadow DOM had issues with SEO and SSR.

Declarative Shadow DOM enables Web Components to be server-rendered.

This improves page speed, accessibility, and SEO rankings.

Browser support is growing, but polyfills exist for wider adoption.


Coming Up Next: Browser Interoperability & Standardization

In the next post, we’ll explore how browsers are working together to ensure Web Standards evolve consistently—and why cross-browser support remains one of the biggest challenges in front-end development.

What do you think of Declarative Shadow DOM? Will you start using it in your projects? Drop a comment below! 🚀

Top comments (0)