# Shadow DOM, шаблоны и стили Спецификация [Shadow DOM](http://w3c.github.io/webcomponents/spec/shadow/) является отдельным стандартом. Частично он уже используется для обычных DOM-элементов, но также применяется для создания веб-компонентов. *Shadow DOM* -- это внутренний DOM элемента, который существует отдельно от внешнего документа. В нём могут быть свои ID, свои стили и так далее. Причём снаружи его, без применения специальных техник, не видно, поэтому не возникает конфликтов. [cut] ## Внутри браузера Концепция Shadow DOM начала применяться довольно давно внутри самих браузеров. Когда браузер показывает сложные элементы управления, наподобие слайдера `` или календаря `` -- внутри себя он конструирует их из самых обычных стилизованных `
`, `` и так далее. С первого взгляда они незаметны, но если в настройках Chrome Development Tools выбрать показ Shadow DOM, то их можно легко увидеть. Например, вот такое содержимое будет у ``: То, что находится под `#shadow-root` -- это и есть Shadow DOM. **Получить элементы из Shadow DOM можно только при помощи специальных JavaScript-вызовов или селекторов. Это не обычные дети, а намного более мощное средство отделения содержимого.** В Shadow DOM выше можно увидеть полезный атрибут `pseudo`. Он нестандартный, существует по историческим причинам. С его помощью можно стилизовать подэлементы через CSS, например, сделаем поле редактирования даты красным: ```html ``` Ещё раз заметим, что `pseudo` -- нестандартный атрибут. Если говорить хронологически, то сначала браузеры начали экспериментировать внутри себя с инкапсуляцией внутренних DOM-структур, а уже потом, через некоторое время, появился стандарт Shadow DOM, который позволяет делать то же самое разработчикам. Далее мы рассмотрим работу с Shadow DOM из JavaScript, по стандарту [Shadow DOM](http://w3c.github.io/webcomponents/spec/shadow/). ## Создание Shadow DOM Shadow DOM можно создать внутри любого элемента вызовом `elem.createShadowRoot()`. Например: ```html

Доброе утро, страна!

``` Если вы запустите этот пример, то увидите, что изначальное содержимое элемента куда-то исчезло и показывается только "Привет из подполья!". Это потому, что у элемента есть Shadow DOM. **С момента создания Shadow DOM обычное содержимое (дети) элемента не отображается, а показывается только Shadow DOM.** Внутрь этого Shadow DOM, при желании, можно поместить обычное содержимое. Для этого нужно указать, куда. В Shadow DOM это делается через "точку вставки" (insertion point). Она объявляется при помощи тега ``, например: ```html

Доброе утро, страна!

``` Теперь вы увидите две строчки: "Доброе утро, страна!" в заголовке, а затем "Привет из подполья". Shadow DOM примера выше в инструментах разработки: Важные детали:
  • Тег `` влияет только на отображение, он не перемещает узлы физически. Как видно из картинки выше, текстовый узел "Доброе утро, страна!" остался внутри `p#elem`. Его можно даже получить при помощи `elem.firstElementChild`.
  • Внутри `` показывается не элемент целиком `

    `, а его содержимое, то есть в данном случае текст "Доброе утро, страна!".

**В `` атрибутом `select` можно указать конкретный селектор содержимого, которое нужно переносить. Например, `` перенесёт только заголовки.** Внутри Shadow DOM можно использовать `` много раз с разными значениями `select`, указывая таким образом, где конкретно какие части исходного содержимого разместить. Но при этом дублирование узлов невозможно. Если узел показан в одном ``, то в следующем он будет пропущен. Например, если сначала идёт ``, а затем ``, то в первом `` будут показаны заголовки `

` с классом `title`, а во втором -- все остальные, кроме уже показанных. В примере выше тег `` внутри пуст. Если в нём указать содержимое, то оно будет показано только в том случае, если узлов для вставки нет. Например потому что ни один узел не подпал под указанный `select`, или все они уже отображены другими, более ранними ``. Например: ```html

Новости

Жили-были старик со старухой, но недавно...
``` При запуске мы увидим, что:
  • Первый `` выведет заголовок.
  • Второй `` вывел бы автора, но так как такого элемента нет -- выводится содержимое самого ``, то есть "Без автора".
  • Третий `` выведет остальное содержимое исходного элемента -- уже без заголовка `

    `, он выведен ранее!

Ещё раз обратим внимание, что `` физически не перемещает узлы по DOM. Он только показывает, где их отображать, а также, как мы увидим далее, влияет на применение стилей. ## Корень shadowRoot После создания корень внутреннего DOM-дерева доступен как `elem.shadowRoot`. Он представляет собой специальный объект, поддерживающий основные методы CSS-запросов и подробно описанный в стандарте как [ShadowRoot](http://w3c.github.io/webcomponents/spec/shadow/#shadowroot-object). Если нужно работать с содержимым в Shadow DOM, то нужно перейти к нему через `elem.shadowRoot`. Можно и создать новое Shadow DOM-дерево из JavaScript, например: ```html

Доброе утро, страна!

``` [warn header="Внутрь встроенных элементов так \"залезть\" нельзя"] На момент написания статьи `shadowRoot` можно получить только для Shadow DOM, созданного описанным выше способом, но не встроенного, как в элементах типа ``. [/warn] ## Шаблоны