Shadow DOM; Style encapsulation; Slots, content projection
Shadow DOM
The Shadow DOM is a key concept in Web Components. It provides a way to encapsulate the internal structure and styles of a custom element, keeping them isolated from the main document's DOM. When you create a custom element, you can attach a shadow root to it using the attachShadow()
method. This creates a separate DOM tree that is scoped to the custom element, with its own styles and event handling.
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = '<h1>Hello from the Shadow DOM!</h1>';
}
}
customElements.define('my-element', MyElement);
Style Encapsulation
The Shadow DOM ensures that styles defined within the custom element's shadow root are scoped to that element, preventing them from leaking out and affecting the rest of the page. This is known as style encapsulation. You can use the :host
pseudo-class to target the custom element itself from within the shadow root:
:host {
display: block;
padding: 10px;
}
:host([disabled]) {
opacity: 0.5;
}
Slots and Content Projection
Slots allow you to define placeholders in your custom element's template that can be filled with content from the outside. This is called content projection.
<template id="my-card-template">
<style>
.card { border: 1px solid #ccc; padding: 10px; }
</style>
<div class="card">
<h2><slot name="title">Default Title</slot></h2>
<div><slot>Default content</slot></div>
</div>
</template>
<script>
class MyCard extends HTMLElement {
constructor() {
super();
const template = document.getElementById('my-card-template');
this.attachShadow({ mode: 'open' }).appendChild(template.content.cloneNode(true));
}
}
customElements.define('my-card', MyCard);
</script>
When using the <my-card>
element, you can fill the slots with your own content:
<my-card>
<span slot="title">Custom Title</span>
<p>This is the main content of the card.</p>
</my-card>
This allows you to create flexible and customizable components.