I love custom elements! I've been building UIs with them since Polymer 0.5 was announced in 2014. One of the things that I've questioned with custom elements has been Shadow DOM and its relationship to CSS. This page is an experiment for comparing custom elements with and without Shadow DOM. Press the buttons below and 1,000 spinners will be displayed on the page, when 'Light' is pressed the custom element uses CSS defined for the whole page, and when 'Shadow' is pressed the custom elements have a style sheet attached to their Shadow DOM, and when 'External' is pressed the CSS for the element is still encapsulated in the Shadow DOM, but it is loaded as an external stylesheet.

N.B. I am not loading any polyfills on this page, so it will only work on browsers with native custom elements support.

This is the code that is running:

CSS


Javascript







The spinner-shadow element follows the suggested best practice of encapsulating the styles via the shadow root. But this seems problematic for a couple of reasons. The first is that it's going to be difficult to pass that CSS through an autoprefixer or any other tooling. The second problem is that this means the CSS will get duplicated for every instance of the element. You can see that by looking in Chrome Dev Tools, that there are 3,000 more nodes on this page when the shadow spinners are displayed as compared to when the light spinners are displayed.

The spinner-external loads the CSS in the Shadow DOM but uses an external stylesheet, which does seem to reduce the number of nodes to below that of the spinner-shadow, but still not close to spinner-light. Also, I don't want to have a separate HTTP request for every element class I use on a page, so this also seems like a non-starter.

So am I holding it wrong? Is there really no way in custom elements to specify the CSS for an element once without resorting to external CSS stylesheets? Or am I reading the Chrome Dev Console page wrong and the Node count doesn't mean what I think it means? I think for now I'm going to stick to avoiding Shadow DOM and specifying the CSS just once in a single stylesheet.

Update: It does look like this is a known issue as there's a proposal to address it in custom elements spec.