CSS isolation with Declarative Shadow DOM

The browser support for DSD is becoming increasingly widespread, and I believe that there are more use cases for it beyond just SSR.

CSS isolation with Declarative Shadow DOM
Photo by Georgie Cobbs / Unsplash

With the release of Safari 16.4, browser support for Declarative Shadow DOM has become widespread. DSD (Declarative Shadow DOM), is a powerful tool, particularly for serializing Web Components to make them compatible with server-side rendering (SSR) environments. However, I see another practical use case for it, which may appeal to larger audiences: using it for style isolation of page elements.

When I worked at sahibinden.com, a leading classified website in Turkey, it was a significant challenge to ensure that classified descriptions remained consistent while still being stylable by users. Users could copy styled content from their websites, complete with unique styles and layouts, and expect to see acceptable results on our classified detail page. Since the description portion of the page was already styled by our CSS definitions, there was a risk of breaking our UIs due to the styles injected into the classified description. As a result, we were doing so much work to keep that page consistent regardless of the style of the classified description.

On those times (it was 6-7 years ago), we were even considering to use iframe to isolate those free-style descriptions from our own HTML content. But even years after, there is no easy solution to address this issue, except ShadowDOM.

Let's consider that we have a product description content within our <main> tag like below:

<main>
    <style>
        .y8y2i1 { color: red; }
        .6h174h { font-family: comic-sans; color: pink; }
    </style>
    <h3 class="y8y2i1">Don't miss this</h3>
    <p class="6h174h">This product is best in its class.</p>
</main>

As you can see we already encapsualted styles of the custom styles of the product description by auto-generating some unique (fingers crossed) class names for them. However, we also know that these tags are still affected by our main CSS styles. If we have CSS rule like main h3 { margin-left: 36px; } this will apply description too. The ugly solution would be to set every possible styles for every possible elements inside description with !important to be sure that they can not be overridden (fingers crossed again), but I believe now we have a better option.

<main>
    <template shadowrootmode="open">
        <style>
            h3 { color: red; }
            p { font-family: comic-sans; color: pink; }
        </style>
        <h3>Don't miss this</h3>
        <p>This product is best in its class.</p>
    </template>
</main>

When you run this, you don't need to give any extra effort to create unique class names or override every possible style rules with !important. And now this works on latest Chrome and Safari without extra JS at all. Check the running example!

What are the benefits we have here?:

  1. Less effort. Just putting user-entered content with their styles inside a template with shadowroot. That's it.
  2. Global styles don't break description content with custom styles.
  3. Styles inside shadow dom won't apply outside of it. So no risk to break your page.
  4. Since styles are now applied with smaller selectors and to a smaller DOM, they are more performant. (https://www.youtube.com/watch?v=nWcexTnvIKI)

Any caveats?

  1. You need to run a -small- pollyfill to cover older browsers.
  2. Some old bots can miss the content inside template tag.

Not that much, huh?

I hope you found this idea inspiring and see the potential benefits of leveraging this API. Such flexible APIs give web developers superpowers, and I appreciate how quickly browser vendors have been responding to developer requests in recent years (thanks to the Interop initiative). Hopefully, the web will experience a new acceleration with the help of these new cross-browser features.

Me on Mastodon: https://synaps.space/@murat