Shadow DOM — это технология, которая позволяет создавать инкапсулированные деревья DOM внутри стандартного DOM-дерева. Основная цель Shadow DOM — изоляция стилей и структуры компонента от внешней среды, что обеспечивает предсказуемое поведение и предотвращает конфликты CSS и JavaScript. Термин sandboxing в контексте Shadow DOM обозначает именно эту изоляцию.
Изоляция стилей Shadow DOM создает отдельное дерево, на которое не распространяются глобальные стили страницы. CSS внутри shadow root действует только на элементы внутри него. Это достигается с помощью двух механизмов:
Пример:
const shadow = document.createElement('div').attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
p { color: red; }
</style>
<p>Текст в shadow DOM</p>
`;
document.body.appendChild(shadow);
В этом примере CSS красит текст <p> только внутри
shadow DOM, не влияя на остальные элементы страницы.
Изоляция структуры DOM Shadow DOM предотвращает
прямой доступ к его внутренним элементам из внешнего DOM, если
используется режим closed. В режиме open
доступ возможен через свойство shadowRoot. Это создает
контролируемый интерфейс компонента, защищая внутреннюю структуру от
непреднамеренных изменений.
Open:
element.attachShadow({ mode: 'open' }) Shadow DOM доступен
через element.shadowRoot. Можно динамически модифицировать
его содержимое извне.
Closed:
element.attachShadow({ mode: 'closed' }) Свойство
shadowRoot возвращает null. Внешний код не
может напрямую изменять содержимое компонента. Это усиливает концепцию
sandboxing, делая компонент полностью самодостаточным.
Стили Shadow DOM позволяет использовать
глобальные переменные CSS (:host,
:host-context, ::slotted) для управления
внешними стилями без выхода за границы компонента.
Пример:
:host {
display: block;
border: 1px solid black;
}
::slotted(span) {
font-weight: bold;
}
:host позволяет задавать стили самому shadow host.::slotted управляет стилями переданных в слот
элементов.Скрипты JavaScript внутри shadow DOM работает с элементами инкапсулированного дерева, но может использовать глобальные функции и объекты. Это создает баланс между изоляцией компонента и доступом к общим библиотекам.
Slots позволяют передавать внешний контент в shadow DOM без нарушения инкапсуляции. Контент, переданный в слот, рендерится внутри shadow root, но остается частью внешнего DOM.
Пример:
const shadow = document.createElement('div').attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style> ::slotted(*) { color: blue; } </style>
<slot></slot>
`;
const wrapper = document.createElement('div');
wrapper.appendChild(shadow);
const span = document.createElement('span');
span.textContent = 'Содержимое слота';
wrapper.appendChild(span);
document.body.appendChild(wrapper);
Здесь <span> отображается внутри shadow DOM с
синим цветом, но остальная часть страницы остается неизменной.
Shadow DOM не обеспечивает полной безопасности от вредоносного кода. Он защищает только от случайного вмешательства в DOM и стили. Для полной изоляции компонентов на уровне безопасности рекомендуется использовать:
iframe с атрибутом sandbox Полностью отделяет скрипты и стили, предотвращая доступ к глобальному DOM.
CSP (Content Security Policy) Ограничивает выполнение неподписанных скриптов и предотвращает инъекции.
Таким образом, sandboxing в Shadow DOM — это механизм структурной и стилевой инкапсуляции, позволяющий создавать устойчивые, предсказуемые компоненты с минимальным риском конфликтов с внешним окружением.
closed для компонентов, внутренние
элементы которых не должны изменяться извне.:host и ::slotted для интеграции
с внешними стилями без нарушения изоляции.Эти принципы позволяют строить масштабируемые и предсказуемые веб-компоненты на основе Lit, максимально используя возможности Shadow DOM для sandboxing.