JavaScript ShadowRoot — тіньовий DOM і ізоляція стилів
ShadowRoot — тіньове дерево всередині елемента: власний DOM, у який не проникають зовнішні стилі й з якого не витікають свої.
Загальний опис
Це справжня інкапсуляція, якої CSS не мав ніколи. Клас .title усередині тіні не зіткнеться з класом .title на сторінці — це два різні світи.
Створюється через element.attachShadow({ mode: 'open' }). Далі всередину кладеться і розмітка, і <style> — і цей стиль діє лише тут.
Саме на цьому побудовані веб-компоненти: віджет можна вставити на будь-який сайт, і його вигляд не зламається чужим CSS.
І звідси ж головна пастка: document.querySelector() не бачить нічого всередині тіні. Шукати треба від кореня: shadowRoot.querySelector().
- Нотатка
-
автор: NagarDmode: 'closed'ховає тінь навіть від власного коду (element.shadowRootдастьnull). Захисту це не додає — обійти можна — а налагодження ускладнює, тож майже завжди берутьopen.
Синтаксис
const shadow = element.attachShadow({ mode: "open" });
властивості
| Властивість | Опис |
|---|---|
| host | Елемент-хост цього тіньового дерева. |
| mode | Режим доступу: open або closed. |
| innerHTML | Розмітка тіньового дерева. |
| activeElement | Сфокусований елемент усередині тіньового дерева. |
| delegatesFocus | Чи делегується фокус першому фокусованому нащадку. |
Переглядачі
| Переглядач | ||||||
|---|---|---|---|---|---|---|
| ShadowRoot | 53+ | 63+ | 10+ | 40+ | 79+ | - |
| Переглядач | ||||
|---|---|---|---|---|
| ShadowRoot | 53+ | yes | yes | 10+ |
Приклади
+ запропонувати свій приклад у пісочниці
Компонент, чиї стилі не б'ються зі стилями сторінки.
HTML
<style>.title { color: red; }</style>
<div id="host"></div>
<p class="title">Я червоний — стиль сторінки</p>
JS
const host = document.getElementById('host');
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
/* діє ЛИШЕ тут — не зіткнеться з .title сторінки */
.title { color: green; font-weight: bold; }
</style>
<p class="title">Я зелений — стиль тіні</p>
`;
// сторінка тіні не бачить
console.log(document.querySelectorAll('.title').length); // 1, а не 2
// шукати треба від кореня тіні
console.log(shadow.querySelector('.title').textContent);
Коментарі
Коментарів ще немає — будьте першим!