Shadow DOM: изоляция разметки и стилей внутри элемента

Что такое Shadow DOM? 🌳

Shadow DOM — это инструмент веб-разработки, который позволяет создавать изолированные DOM-деревья внутри обычных DOM-элементов. Это как секретный отсек в вашем HTML, куда не проникают глобальные стили и внешний JavaScript! 🔒

Зачем это нужно?
👉 Избежать конфликтов стилей.
👉 Создать переиспользуемые компоненты.
👉 Скрыть сложную внутреннюю структуру элемента.


Как создать Shadow DOM? 🛠️

Прикрепить Shadow DOM к элементу можно с помощью JavaScript:

<div id="host-element"></div>

<script>
  const host = document.getElementById('host-element');
  const shadowRoot = host.attachShadow({ mode: 'open' });

  shadowRoot.innerHTML = `
    <style>
      p { color: red; } /* Стиль будет работать только внутри Shadow DOM! */
    </style>
    <p>Привет из Shadow DOM!</p>
  `;
</script>

🔑 Ключевые моменты:
- mode: 'open' — позволяет обращаться к Shadow DOM извне через element.shadowRoot.
- mode: 'closed' — полностью закрывает доступ (используется редко).


Изоляция стилей 🎨

Одна из самых мощных возможностей Shadow DOM — стилевая изоляция. Стили внутри Shadow DOM не влияют на внешнюю страницу, а глобальные стили не проникают внутрь!

<div id="styled-widget"></div>
<style>
  /* Глобальный стиль */
  p { color: blue; }
</style>

<script>
  const widget = document.getElementById('styled-widget');
  const shadow = widget.attachShadow({ mode: 'open' });

  shadow.innerHTML = `
    <style>
      p {
        color: green;
        border: 2px dashed black;
        padding: 10px;
      }
    </style>
    <p>Этот текст будет зеленым, несмотря на глобальный стиль!</p>
  `;
</script>

Слоты (Slots) — дыры в изоляции 🕳️

Хотите частично нарушить изоляцию? Используйте <slot>! Это специальные места, куда можно вставлять контент извне Shadow DOM.

<user-card>
  <span slot="username">Данила Бежин</span>
  <span slot="email">danila@example.com</span>
</user-card>

<script>
  class UserCard extends HTMLElement {
    constructor() {
      super();
      const shadow = this.attachShadow({ mode: 'open' });
      shadow.innerHTML = `
        <div class="card">
          <h2><slot name="username">Имя пользователя</slot></h2>
          <p><slot name="email">Email</slot></p>
        </div>
      `;
    }
  }

  customElements.define('user-card', UserCard);
</script>

Что происходит:
- Контент из обычного DOM вставляется в указанные слоты.
- Если слот пуст, отображается контент по умолчанию.


Практический пример: Кастомный прогресс-бар ⏳

Давайте создадим переиспользуемый компонент прогресс-бара с изолированными стилями!

<progress-bar value="75"></progress-bar>

<script>
  class ProgressBar extends HTMLElement {
    constructor() {
      super();

      const shadow = this.attachShadow({ mode: 'open' });
      shadow.innerHTML = `
        <style>
          .container {
            width: 100%;
            height: 20px;
            background: #eee;
            border-radius: 10px;
            overflow: hidden;
          }
          .fill {
            height: 100%;
            background: linear-gradient(to right, #4CAF50, #8BC34A);
            width: ${this.getAttribute('value')}%;
            transition: width 0.3s;
          }
        </style>
        <div class="container">
          <div class="fill"></div>
        </div>
      `;
    }
  }

  customElements.define('progress-bar', ProgressBar);
</script>

🔥 Почему это круто:
- Компонент можно использовать где угодно.
- Стили не конфликтуют с другими элементами.
- Внешний код не может случайно сломать внутреннюю структуру.


Когда использовать Shadow DOM? 🤔

  1. Веб-компоненты — идеальный вариант для создания самодостаточных UI-элементов.
  2. Виджеты — если встраиваете код на сторонние сайты.
  3. Сложные UI-элементы — где нужно защитить внутреннюю структуру.

🚨 Ограничения:
- Shadow DOM не поддерживается в IE11 (нужен полифилл).
- Может усложнить отладку (но в Chrome DevTools есть специальная поддержка).


Погружаемся глубже 🏊‍♂️

Хотите увидеть Shadow DOM в действии? Откройте DevTools (Ctrl+Shift+I или Cmd+Opt+I на Mac) и посмотрите на элементы <video> или <input type="range"> — это встроенные компоненты браузера, использующие Shadow DOM!

Для тех, кто хочет стать настоящим мастером веб-компонентов, рекомендую курс Данилы Бежина на YouTube: https://www.youtube.com/@DanilaBezhin. Он отлично объясняет сложные концепты простым языком!

Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty