Shadow DOM — Terminology & Slots

Please read my first story about Shadow DOM if you are not familiar with Shadow DOM.

Shadow DOM enables local scoping for HTML & CSS.

Light DOM, Shadow DOM vs. Flattened DOM

Let’s explain the terminology

A Light DOM is the set of DOM elements a user of your component writes between the opening and closing tags. This DOM lives outside the component’s shadow DOM. It is the element’s actual children. In this example, the image and cite are the elements of the Light DOM.

<custom-picture>
^^^^^^^^^^^^^^^^^^^^^^^^^^^
#shadow-root
___________________________

<!--Light DOM-->
<img src="https://path.to/a-kitten.png">
<cite>A Nice Kitten!</cite>
<!--Light DOM ends-->
</custom-picture>

The Shadow DOM is the DOM a component author writes. Shadow DOM is local to the component and defines its scoped CSS, structure and encapsulates your implementation details.

#shadow-root
<style>...</style>
<slot name="icon"></slot>
<span id="wrapper">
<slot>Button</slot>
</span>

Flattened DOM tree is what you see in the DevTools and what is rendered on the page.

<better-button>
#shadow-root
<style>...</style>
<slot name="icon">
<img src="xxx.svg" slot="icon">
</slot>
<span id="wrapper">
<slot>
<span>Settings</span>
</slot>
</span>
</better-button>

Slots

Slots are placeholders inside your component that users can fill with their own markup.

If you create custom components, you want to only provide the necessary markup that goes into a particular component.

Slots are the way we can arrange that markup however we want. Styling based on different cases and group them.

There are two aspects of slots:

  • Light DOM Elements : They say which slot they wanna go into.
<custom-picture>
<!--Light DOM <img> saying it should be put into the "profile-picture" slot-->
<img src="assets/user.svg" slot="profile-picture">
</custom-picture>

img is supposed to put into the profile-picture slot.

  • The Actual Slot : The <slot> element, residing somewhere in shadow DOM with a name for itself to be found by light DOM.
<custom-picture>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#shadow-root
<slot name="profile-picture">
<!--The <img> from the light DOM gets rendered here!-->
</slot>
_________________________________________

If you don’t provide the slot attribute to the image tag nothing gets rendered.

Light DOM elements only get rendered if they are part of the Shadow DOM and this only happens by putting them in slots.

In this Codepen example you can see how you can use a template and define style within the template and create a new custom component called <my-paragraph> which can have changing text with slots.

I hope this made you less confused than before :)

I found these links to be very helpful:

I like to do crazy things with CSS & JavaScript. My brain occasionally runs out of memory so I need to write down my thoughts.