Search code examples
web-componentshadow-domtemplatetags

How do you avoid repeating styles in shadow DOM?


I'm new to web components, so not sure if there's an easy answer or best practice on this one.

If I want to create a series of repeating elements with encapsulated style how do I avoid repeating the style block with each element.

A reduced version of the code I'm using is:

<ul id="wrapper"></ul>

<template id="template">
  <style>
    li { color: red }
  </style>

  <li></li>
</template>

<script>
var wrapper = document.getElementById('wrapper');
var tpl = document.getElementById('template');
var shadow = wrapper.createShadowRoot();
var arr = ['a', 'b', 'c'];

for(var i = 0, ii = arr.length; i < ii; i++) {
  tpl.content.querySelector('li').textContent = arr[i];

  var clone = document.importNode(tpl.content, true);

  shadow.appendChild(clone);
}
</script>

The problem I have with that is that the shadow DOM has a duplicated style block for each <li>, and am not sure the best way round it.

I have tried nesting a template and that is either never going to work or I'm not doing it right.


Solution

  • Fast-forward to 2022 and we now have "constructable stylesheets". Reference here. Basically the browser is smart enough to use only a single constructed stylesheet for all those copies of your webcomponent on the page! :)

    Quoting from the article:

    Constructable Stylesheets make it possible to define and prepare shared CSS styles, and then apply those styles to multiple Shadow Roots or the Document easily and without duplication. Updates to a shared CSSStyleSheet are applied to all roots into which it has been adopted