Web Components, Shadow DOM, Shadow CSS ;tldr
Tags: webcomponents, shadowdom, customelements, javascript
Published: 2020-04-16 09:34:28

I am not going to tell you that you should jump into Web Components and that it is the new cool shit that will replace your framework.

I am trying to resolve the questions about the following topics as efficient as possible to get your head around it:

1. What is a Web Component?
2. What is Shadow DOM?
3. What is a Slot (and what is LightDOM)?
4. Which CSS selectors do I need with Shadow DOM?

---

## 1. What is a Web Component?
A Web Component is anything that is defined via `customElements.define` Interface.

It does not matter if you use Shadow DOM or whatever. If you use that API for a custom tag you are using a Web Component.

### 1.1. How can I use a Web Component?

```html
<your-tag></your-tag>
<script>
// most simple example of a Web Component:
customElements.define('your-tag', class extends HTMLElement {
  connectedCallback() {
    this.innerHTML = 'Hello world!';
  }
}
</script>
```

They are [not self-closing](https://stackoverflow.com/questions/23961178/do-custom-elements-require-a-close-tag) so do not do it! 

### 1.2. The lifecycle of a Web Component

You have [4 of 5 methods](https://developer.mozilla.org/de/docs/Web/Web_Components/Using_custom_elements) that you might want to use in your Web Component commonly:

- `constructor()` Use for data pre-fetching etc.
- `connectedCallback()` tells you when it is mounted in the DOM
- `disconnectedCallback()` tells you when it is unmounted from the DOM
- `attributeChangedCallback(...)` tells you when an attribute on your element has changed 
  - This one comes in combination with `static get observedAttributes() {return ['foo', 'bar']; }`  which tells which attributes to observe and call the callback on

---

## 2. What is Shadow DOM?

```javascript
customElements.define('your-tag', class extends HTMLElement {
  connectedCallback() {
    this.innerHTML = 'Hello Light';
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.innerHTML = 'Hello Darkness';
  }
}

```


Shadow DOM first of all is a DOM Node as every other node.
The Shadow DOM Node however cannot be found via `querySelector` nor can everything inside of it be found via `querySelector` from the outside.
Also the outside CSS does not apply.

Some quick clarifications:

**Shadow DOM**...
- is **not** a security layer!
- does not scope away JS 
- scopes CSS and HTML
- means that if you have defined styles and a `videoplayer` lib on your document they will not find any DOM inside your Shadow DOM nor put any styling on anything within


### 2.1. If I have a global library `say` in my document with a method `hello()` can I call it from inside the Shadow DOM?

Yes! See: https://codesandbox.io/s/say-hello-qswww?file=/src/index.js
You define the Web Component in your normal JS scope.

### 2.2. Why Shadow DOM?

I can see exactly 2 answers here:

- You need Isolation of CSS/HTML 
- You want to use the Slot feature

## 3. What is a Slot, what is Light DOM?


### 3.1. Light DOM

Light DOM != Normal DOM. Light DOM is referred as the DOM in a ShadowDOM-Web-Component that is NOT in the Shadow DOM. 

If you check my [live example ](https://codesandbox.io/s/light-dom-vs-shadow-dom-cmyh9?file=/src/index.js) you will see that you do not see the Light DOM content ("Hello Light") because the Shadow DOM content takes over the Web Component once attached. The Light DOM then only can be referenced via Slots (next section).

### 3.2. Slot

If you put `<slot><slot>` anywhere inside of Shadow DOM and you have content in the Light DOM then the content in the Light DOM that "got missing" in section 3.1. will show up where the `<slot>` sits.

It is literally a placeholder that acts as if the slotted content would be copied to that exact point where the slot is. So in your head just think of: Where the `<slot>` tag is everything from outside the Shadow DOM will be "copied" (virtually) to.

https://codesandbox.io/s/light-dom-vs-shadow-dom-cmyh9?file=/src/index.js


## 4. Which CSS Selectors do I need with Shadow DOM?

Most probably you will need the following:

- `::slotted()`
- `:host()`
- `:host-context()`

I created a Sandbox which hopefully helps to understand how it works (post in the comments if you want further text explanation here):

https://codesandbox.io/s/gracious-saha-928yt?file=/index.html .


### Sources

- https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
- https://developer.mozilla.org/en-US/docs/Web/CSS/:host()
- https://developer.mozilla.org/en-US/docs/Web/CSS/:host-context()