Suppose a custom element contains a `<div>` that page code can find and change. A shadow root gives the element a separate DOM tree for its internal content. The element is the shadow host; the root sits at the boundary between that host and the Shadow DOM. Like a document fragment, it is separate from the page’s main DOM tree. section 8.2
Listing 8.2. Using the Shadow DOM in a simple component
connectedCallback() {
this.attachShadow({mode: 'open'}); #1
this.shadowRoot.innerHTML =
`<div class="inside-component">My Component</div>` #2
}
The minimal open-mode example attaches a root, then puts markup inside it through `this.shadowRoot`. section 8.2
Pass a mode when calling `attachShadow`: `open` or `closed`. With an open root, `this.shadowRoot` provides access from the component, and outside code can reach inside by first selecting the host. A page-level `document.querySelector('.inside-component')` alone will not cross the boundary. So open mode changes ordinary DOM access; it does not make the internals inaccessible. section 8.2
Keep a reference to a closed root
To build inside a closed root, retain the value returned by `attachShadow({mode: 'closed'})`: `const root = this.attachShadow({mode: 'closed'}); root.innerHTML = '<div>My Component</div>';`. Do not use `this.shadowRoot` for that initialization. Closed mode limits normal access, but it is not a security boundary against determined interference. section 8.2
A shadow root also makes slots useful. Attach it to a custom element, append a template containing named `<slot>` elements, then put matching `slot` attributes on content inside the element’s tag. An unfilled slot displays its fallback content. This lets the element keep its layout while accepting values supplied by its user. section 7.5
The boundary matters for CSS too: ordinary page-level selectors do not style matching elements inside the root, and internal rules do not creep into other shadow trees. To style the host from inside, use `:host` rather than the custom element’s tag name. Encapsulation has nuance, though: inherited text styling can still affect content inside. section 9.2
Need a non-Shadow-DOM fallback? Store either the attached root or the host itself in one `root` property. Move DOM-dependent initialization to `connectedCallback`: without a shadow root, the page-provided DOM is not yet available in the constructor. Selectors and host styles may also need corresponding changes. section 12.1
