Сервис для
сео - оптимизаторов

Найди ошибки на сайте
Ошибки мешают продвижению сайта
Исправь ошибки на сайте
Сайт без ошибок продвигать легче
Получи новых клиентов
Новые клиенты принесут больше прибыль

Shadow DOM 201: CSS и стилизация

  1. Вступление
  2. Инкапсуляция стиля
  3. Стилизация хост-элемента
  4. Реагирование на состояния пользователей
  5. Тематический элемент
  6. Поддержка нескольких типов хостов из одного теневого корня
  7. Псевдоэлемент :: shadow
  8. Работа с querySelector ()
  9. Стилизация родных элементов
  10. Создание стиля крючки
  11. Использование :: shadow и / deep /
  12. Использование CSS-переменных
  13. Стилизация распределенных узлов
  14. :: псевдоэлемент контента
  15. Лайт ДОМ
  16. Заключение

В этой статье описывается старая версия Shadow DOM (v0). Если вы заинтересованы в использовании Shadow DOM, ознакомьтесь с нашей новой статьей по адресу developers.google.com, " Shadow DOM v1: автономные веб-компоненты Msgstr "Он охватывает все в новой спецификации Shadow DOM v1, поставляемой в Chrome 53, Opera и Safari 10.

В этой статье обсуждается больше удивительных вещей, которые вы можете сделать с Shadow DOM. Он основан на концепциях, обсуждаемых в Shadow DOM 101 , Если вы ищете введение, посмотрите эту статью.

Вступление

Давайте смотреть правде в глаза. Нет ничего сексуального в разметке без стилей. К счастью для нас, блестящие люди за веб-компоненты предвидел это и не оставил нас в покое. CSS Scoping Module определяет множество параметров для стилизации содержимого в теневом дереве.

В Chrome включите «Включить экспериментальные функции веб-платформы» в about: flags, чтобы экспериментировать со всем, что описано в этой статье.

Инкапсуляция стиля

Одной из основных функций Shadow DOM является граница тени , У него много приятных свойств, но одним из лучших является то, что он обеспечивает бесплатную инкапсуляцию стиля. Заявлено иначе:

Стили CSS, определенные в Shadow DOM, ограничиваются ShadowRoot. Это означает, что стили инкапсулированы по умолчанию.

Ниже приведен пример. Если все идет хорошо и ваш браузер поддерживает Shadow DOM (это не так!), Вы увидите «Shadow DOM».

<div> <h3> Light DOM </ h3> </ div> <script> var root = document.querySelector ('div'). createShadowRoot (); root.innerHTML = '<style> h3 {color: red; } </ style> '+' <h3> Shadow DOM </ h3> '; </ Скрипт>

Об этой демонстрации есть два интересных замечания:

  • Есть другие h3s на этой странице , но единственный, который соответствует селектору h3 и поэтому имеет красный стиль, это тот, что находится в ShadowRoot. Опять же, стили по умолчанию.
  • Другие правила стилей, определенные на этой странице и предназначенные для h3, не попадают в мой контент. Это потому, что селекторы не пересекают границу тени .

Мораль истории? У нас есть стиль инкапсуляции из внешнего мира. Спасибо Shadow DOM!

Стилизация хост-элемента

Хост: позволяет выбрать и стилизовать элемент, содержащий теневое дерево:

<button class = "red"> Моя кнопка </ button> <script> var button = document.querySelector ('button'); var root = button.createShadowRoot (); root.innerHTML = '<style>' + ': host {text-transform: uppercase; } '+' </ style> '+' <content> </ content> '; </ Скрипт>

Моя кнопка

Одна хитрость заключается в том, что правила на родительской странице имеют более высокую специфичность, чем: правила хоста, определенные в элементе, но более низкую специфичность, чем атрибут стиля, определенный в элементе хоста. Это позволяет пользователям переопределить ваш стиль снаружи. : host также работает только в контексте ShadowRoot, поэтому вы не можете использовать его вне Shadow DOM.

Функциональная форма: host (<selector>) позволяет вам указывать на элемент host, если он соответствует <selector>.

Пример - соответствует, только если сам элемент имеет класс .different (например, <x-foo class = "different"> </ x-foo>):

: host (.different) {...}

Реагирование на состояния пользователей

Типичный вариант использования для: host - когда вы создаете Таможенный элемент и хотите реагировать на различные состояния пользователя (: hover,: focus,: active и т. д.).

<style>: host {opacity: 0.4; переход: непрозрачность 420 мс, облегчение вывода; }: host (: hover) {непрозрачность: 1; }: хост (: активный) {позиция: относительная; верх: 3 пикселя; слева: 3 пикселя; } </ style>

Моя кнопка

Тематический элемент

Псевдокласс: host-context (<selector>) соответствует элементу host, если он или любой из его предков соответствуют <selector>.

Обычное использование: host-context () - для размещения элемента на основе его окружения. Например, многие люди делают темы, применяя класс к <html> или <body>:

<body class = "different"> <x-foo> </ x-foo> </ body>

Вы можете: host-context (.different) стилизовать <x-foo>, когда он является потомком элемента с классом .different:

: host-context (.different) {цвет: красный; }

Это дает вам возможность инкапсулировать правила стиля в Shadow DOM элемента, которые уникально оформляют его в зависимости от его контекста.

Поддержка нескольких типов хостов из одного теневого корня

Другое использование для: host - это если вы создаете библиотеку тем и хотите поддерживать стилизацию многих типов элементов хоста из одной и той же Shadow DOM.

: host (x-foo) {/ * Применяется, если хост является элементом <x-foo>. * /}: host (x-foo: host) {/ * То же, что и выше. Применяется, если хост является элементом <x-foo>. * /}: host (div) {{/ * Применяется, если элементом host является <div>. * /}

Псевдоэлемент :: shadow и / deep / combinator похожи на меч Ворпала с авторитетом CSS. Они позволяют проникать через границу Shadow DOM для стилизации элементов в теневых деревьях.

Псевдоэлемент :: shadow

Если элемент имеет хотя бы одно теневое дерево, псевдоэлемент :: shadow соответствует самому корню тени. Это позволяет вам писать селекторы, которые стилизуют узлы внутри теневого элемента.

Например, если элемент содержит теневой корень, вы можете написать #host :: shadow span {}, чтобы стилизовать все промежутки в его теневом дереве.

<style> #host :: shadow span {color: red; } </ style> <div id = "host"> <span> Light DOM </ span> </ div> <script> var host = document.querySelector ('div'); var root = host.createShadowRoot (); root.innerHTML = "<span> Shadow DOM </ span>" + "<content> </ content>"; </ Скрипт>

Пример (пользовательские элементы) - <x-tabs> имеет дочерние элементы <x-panel> в Shadow DOM. Каждая панель содержит собственное теневое дерево, содержащее заголовки h2. Чтобы стилизовать эти заголовки с главной страницы, можно написать:

x-tabs :: shadow x-panel :: shadow h2 {...}

/ Deep / combinator похож на :: shadow, но более мощный. Он полностью игнорирует все теневые границы и пересекает любое количество теневых деревьев. Проще говоря, / deep / позволяет вам углубляться в кишки элемента и нацеливаться на любой узел.

Комбинация / deep / combinator особенно полезна в мире пользовательских элементов, где обычно используется несколько уровней Shadow DOM. Основные примеры - вложение множества пользовательских элементов (каждый из которых содержит свое собственное теневое дерево) или создание элемента, который наследуется от другого, используя <Тень> ,

Пример (пользовательские элементы) - выберите все элементы <x-panel>, которые являются потомками <x-tabs>, в любом месте дерева:

x-tabs / deep / x-panel {...}

Пример - стилизация всех элементов с классом .library-theme в любом месте теневого дерева:

body / deep / .library-theme {...}

Работа с querySelector ()

Как .shadowRoot открывает теневые деревья для обхода DOM, комбинаторы открывают теневые деревья для обхода селектора. Вместо написания вложенной цепочки безумия, вы можете написать одно утверждение:

// Не весело. document.querySelector ('x-tabs'). shadowRoot .querySelector ('x-panel'). shadowRoot .querySelector ('# foo'); // Веселье. document.querySelector ('x-tabs :: shadow x-panel :: shadow #foo');

Стилизация родных элементов

Нативные элементы управления HTML - это вызов стилю. Многие люди просто сдаются и катятся самостоятельно. Однако с помощью :: shadow и / deep / можно стилизовать любой элемент веб-платформы, использующий Shadow DOM. Отличными примерами являются типы <input> и <video>:

video / deep / input [type = "range"] {background: hotpink; }

Создание стиля крючки

Кастомизация хороша. В некоторых случаях вы можете захотеть проделать дыры в защитном щите вашей Тени и создать крючки для других.

Использование :: shadow и / deep /

Там много силы позади / глубокая /. Это дает авторам компонентов способ обозначать отдельные элементы как стилизуемые или множество элементов как тематически.

Пример - стиль всех элементов, которые имеют класс .library-theme, игнорируя все теневые деревья:

body / deep / .library-theme {...}

Использование CSS-переменных

Мощный способ создания темных хуков будет через Переменные CSS , По сути, создание «заполнителей стиля» для заполнения другими пользователями.

Представьте себе автора пользовательского элемента, который выделяет переменные заполнители в их Shadow DOM. Один для стилизации шрифта внутренней кнопки, а другой для его цвета:

button {color: var (- button-text-color, pink); / * цвет по умолчанию будет розовый * / font-family: var (- button-font); }

Затем встраиватель элемента определяет эти значения по своему вкусу. Возможно, чтобы соответствовать супер крутой теме Comic Sans на их собственной странице:

#host {--button-text-color: green; --button-font: "Comic Sans MS", "Comic Sans", курсив; }

Из-за того, что CSS-переменные наследуют, все очень красиво, и это прекрасно работает! Вся картина выглядит так:

<style> #host {--button-text-color: green; --button-font: "Comic Sans MS", "Comic Sans", курсив; } </ style> <div id = "host"> Узел хоста </ div> <script> var root = document.querySelector ('# host'). createShadowRoot (); root.innerHTML = '<style>' + 'button {' + 'color: var (- button-text-color, pink);' + 'font-family: var (- button-font);' + '}' + '</ style>' + '<content> </ content>'; </ Скрипт>

Стилизация распределенных узлов

Распределенные узлы - это элементы, которые отображаются на точка вставки (элемент <content>). Элемент <content> позволяет вам выбирать узлы в Light DOM и отображать их в предопределенных местах в Shadow DOM. Они не логично в Shadow DOM; они все еще дети элемента хоста. Точки вставки - это просто рендеринг.

Распределенные узлы сохраняют стили из основного документа. То есть правила стиля с главной страницы продолжают применяться к элементам, даже если они отображаются в точке вставки. Опять же, распределенные узлы по-прежнему логически находятся на свету и не двигаются Они просто делают в другом месте. Однако, когда узлы распределяются в Shadow DOM, они могут принимать дополнительные стили, определенные в теневом дереве.

:: псевдоэлемент контента

Распределенные узлы являются дочерними по отношению к элементу хоста, так как мы можем нацелить их из Shadow DOM? Ответ - псевдоэлемент CSS :: content. Это способ нацеливания на узлы Light DOM, которые проходят через точку вставки. Например:

:: content> h3 стилизует любые теги h3, которые проходят через точку вставки.

Давайте посмотрим на пример:

<div> <h3> Light DOM </ h3> <section> <div> Я не подчеркнут </ div> <p> Я подчеркнут в Shadow DOM! </ p> </ section> </ div> <script> var div = document.querySelector ('div'); var root = div.createShadowRoot (); root.innerHTML = '\ <style> \ h3 {color: red; } \ content [select = "h3"] :: content> h3 {\ color: green; \} \ :: раздел содержимого p {\ text-ornament: underline; \} \ </ style> \ <h3> Shadow DOM </ h3> \ <content select = "h3"> </ content> \ <content select = "section"> </ content> '; </ Скрипт>

Лайт ДОМ

Я не подчеркнул

Я подчеркнут в Shadow DOM!

Вы должны увидеть «Shadow DOM» и «Light DOM» под ним. Также обратите внимание, что «Light DOM» по-прежнему сохраняет стили (поля и т. Д.), Определенные на этой странице. Это потому, что стили страницы по-прежнему совпадают!

Заключение

Как авторы пользовательских элементов, у нас есть множество вариантов управления внешним видом нашего контента. Shadow DOM формирует основу для этого дивного нового мира.

Shadow DOM дает нам инкапсуляцию в ограниченном стиле и позволяет впустить столько (или так мало) внешнего мира, как мы выберем. Определяя пользовательские псевдоэлементы или включая заполнители CSS-переменных, авторы могут предоставить сторонним производителям удобные приемы для стилизации для дальнейшей настройки своего контента. В целом, веб-авторы полностью контролируют то, как их контент представлен.

Благодаря Доминик Куни а также Дмитрий Глазков для просмотра содержания этого урока.

Мораль истории?