Shadow DOM
Коротко
Механизм, который прикрепляет к элементу отдельное скрытое дерево узлов со своими стилями: внешний CSS не задевает его разметку, а внутренние стили не выходят наружу.
Что такое «Shadow DOM»
Главная боль больших страниц — стили конфликтуют. Класс .title из темы ломает виджет чата, а стили виджета портят кнопки сайта. Теневое дерево решает это на уровне браузера: у элемента-хозяина появляется собственный корень, и всё, что внутри, живёт по своим правилам. Это основа веб-компонентов наряду с пользовательскими элементами и тегом template.
Браузеры давно пользуются этим механизмом сами. Ползунок input type="range", элементы управления video — всё это внутренняя теневая разметка, которую видно в инструментах разработчика при включённой настройке показа user-agent shadow DOM.
Пример на JavaScript
class PriceTag extends HTMLElement {
connectedCallback() {
const root = this.attachShadow({ mode: 'open' });
root.innerHTML = `
<style>p { color: var(--accent, #c00); font-weight: 700; }</style>
<p><slot></slot></p>`;
}
}
customElements.define('price-tag', PriceTag);
// <price-tag>1 990</price-tag>
Правило p внутри компонента действует только в его теневом дереве и не перекрашивает абзацы страницы. Содержимое тега попадает в slot. Компонент можно подключить и без JavaScript — декларативно, через <template shadowrootmode="open"> внутри элемента.
Что проникает через границу
- Наследуемые свойства —
color,font-familyи подобные — переходят внутрь от хозяина, как обычно. - Пользовательские свойства CSS тоже наследуются, поэтому через них удобно делать темизацию компонента.
- Снаружи можно стилизовать сам хозяин и части, помеченные атрибутом
part, через::part(). Обычные селекторы внутрь не попадают. - События всплывают наружу, но браузер подменяет их цель на элемент-хозяин, чтобы не раскрывать внутреннее устройство.
Режим open позволяет добраться до дерева через свойство shadowRoot, closed его скрывает. Защитой данных это не является — изоляция касается только стилей и узлов DOM.

