<template> элемент HTML content template
Базовый уровень Широко доступно *
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и в разных версиях браузеров. Она доступна во всех браузерах с ноября 2015 года.
* Некоторые части этой функции могут поддерживаться в разной степени.
Элемент <template> HTML служит механизмом для хранения фрагментов HTML, которые можно использовать позднее с помощью JavaScript или сразу создать в теневом DOM.
Атрибуты
Этот элемент включает глобальные атрибуты.
shadowrootmode-
Создаёт теневой корень для родительского элемента. Это декларативная версия метода
Element.attachShadow(), принимающая те же перечислимые значения.open-
Открывает доступ к внутреннему DOM теневого корня из JavaScript (рекомендуется для большинства случаев).
closed-
Скрывает внутренний DOM теневого корня от JavaScript.
Примечание: HTML-парсер создаёт объект
ShadowRootв DOM для первого<template>в узле, у которого этот атрибут имеет допустимое значение. Если атрибут не задан или задано недопустимое значение либо если в том же родителе уже декларативно созданShadowRoot, создаётся элементHTMLTemplateElement. После разбора элементHTMLTemplateElementнельзя преобразовать в теневой корень, например, задавHTMLTemplateElement.shadowRootMode.Примечание: В старых руководствах и примерах, ранее поддерживавшихся в Chrome 90–110, может встречаться нестандартный атрибут
shadowroot. С тех пор этот атрибут был удалён и заменён стандартным атрибутомshadowrootmode. shadowrootclonable-
Задаёт значение свойства
clonableобъектаShadowRoot, созданного с помощью этого элемента, равнымtrue. Если атрибут задан, клон хоста теневого DOM (родительского элемента этого<template>), созданный с помощьюNode.cloneNode()илиDocument.importNode(), будет содержать теневой корень. shadowrootcustomelementregistry-
Задаёт для свойства
customElementRegistryобъектаShadowRoot, созданного с помощью этого элемента, значениеnullвместо реестра пользовательских элементов документа. Это позволяет позднее прикрепить область действияCustomElementRegistryс помощьюCustomElementRegistry.initialize(). shadowrootdelegatesfocus-
Задаёт значение свойства
delegatesFocusобъектаShadowRoot, созданного с помощью этого элемента, равнымtrue. Если атрибут задан и выбран нефокусируемый элемент в теневом дереве, фокус передаётся первому фокусируемому элементу в дереве. Значение по умолчанию —false. shadowrootreferencetarget-
Задаёт значение свойства
referenceTargetобъектаShadowRoot, созданного с помощью этого элемента. Значением должен быть идентификатор элемента внутри теневого DOM. Если атрибут задан, ссылки на целевой элемент-хост из-за пределов теневого DOM будут указывать на указанный элемент как на фактическую цель ссылки на элемент-хост. shadowrootserializable-
Задаёт значение свойства
serializableобъектаShadowRoot, созданного с помощью этого элемента, равнымtrue. Если атрибут задан, теневой корень можно сериализовать, вызвав методыElement.getHTML()илиShadowRoot.getHTML()с параметромoptions.serializableShadowRoots, заданным какtrue. Значение по умолчанию —false. shadowrootslotassignment-
Задаёт свойство
slotAssignmentобъектаShadowRoot, созданного с помощью этого элемента. Это декларативный эквивалент параметраslotAssignmentметодаElement.attachShadow().named-
Элементы автоматически распределяются по элементам
<slot>внутри этого теневого корня. Это значение по умолчанию.Элементы с атрибутом
slotназначаются первому элементу<slot>в шаблоне, у которого есть соответствующий атрибутname. Если несколько элементов указывают одно и то же имя слота, все они добавляются в первый слот шаблона с этим именем и отображаются в порядке объявления. Все элементы без имени — элементы, у которых не указан атрибутslot, — назначаются слоту по умолчанию в порядке объявления. Это первый безымянный<slot>в шаблоне. manual-
Элементы назначаются определённым слотам вручную с помощью
HTMLSlotElement.assign(). Автоматическое назначение не выполняется.
Примечания по использованию
У этого элемента не может быть содержимого, поскольку всё, что вложено в него в исходном коде HTML, фактически не становится дочерними узлами элемента <template>. Свойство Node.childNodes элемента <template> всегда пусто, а получить доступ к вложенному содержимому можно только через специальное свойство content. Однако, если вызвать Node.appendChild() или аналогичные методы для элемента <template>, дочерние узлы будут добавлены непосредственно в сам элемент <template>. Это нарушает его модель содержимого и фактически не обновляет DocumentFragment, возвращаемый свойством content.
Из-за особенностей разбора элемента <template> все открывающие и закрывающие теги <html>, <head> и <body> внутри шаблона являются синтаксическими ошибками и игнорируются парсером, поэтому <template><head><title>Test</title></head></template> совпадает с <template><title>Test</title></template>.
Элемент <template> можно использовать двумя основными способами.
Фрагмент документа шаблона
По умолчанию содержимое элемента не отображается. Соответствующий интерфейс HTMLTemplateElement содержит стандартное свойство content (без соответствующего атрибута содержимого/разметки). Это свойство content доступно только для чтения и содержит DocumentFragment с поддеревом DOM, представленным шаблоном.
Методы Node.cloneNode() и Document.importNode() создают копию узла. Разница в том, что importNode() клонирует узел в контексте вызывающего документа, а cloneNode() использует документ клонируемого узла. Контекст документа определяет CustomElementRegistry для создания любых пользовательских элементов. Поэтому используйте document.importNode() для клонирования фрагмента content, чтобы пользовательские элементы-потомки создавались с использованием определений текущего документа, а не отдельного документа, которому принадлежит содержимое шаблона. Подробнее см. примеры на странице Node.cloneNode().
Обратите внимание, что к самому контейнеру DocumentFragment не следует прикреплять данные. Подробнее см. пример Данные DocumentFragment не клонируются.
Декларативный теневой DOM
Если элемент <template> содержит атрибут shadowrootmode со значением open или closed, HTML-парсер немедленно создаёт теневой DOM. Элемент заменяется в DOM его содержимым, обёрнутым в ShadowRoot, который прикрепляется к родительскому элементу. Это декларативный эквивалент вызова Element.attachShadow() для прикрепления теневого корня к элементу.
Если атрибут shadowrootmode имеет любое другое значение или у элемента отсутствует атрибут shadowrootmode, парсер создаёт HTMLTemplateElement. Аналогично, если имеется несколько декларативных теневых корней, только первый заменяется на ShadowRoot, а последующие экземпляры разбираются как объекты HTMLTemplateElement.
Другие атрибуты с префиксом shadowroot позволяют декларативно настраивать ShadowRoot, например управлять распределением слотов.
Примеры
>Создание строк таблицы
Сначала рассмотрим HTML-код примера.
<table id="producttable">
<thead>
<tr>
<td>UPC_Code</td>
<td>Product_Name</td>
</tr>
</thead>
<tbody>
<!-- existing data could optionally be included here -->
</tbody>
</table>
<template id="productrow">
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
Сначала создаётся таблица, в которую позднее с помощью JavaScript будет добавлено содержимое. Далее идёт шаблон, описывающий структуру фрагмента HTML для одной строки таблицы.
После создания таблицы и определения шаблона с помощью JavaScript добавим в таблицу строки, каждая из которых будет построена на основе шаблона.
// Test to see if the browser supports the HTML template element by checking
// for the presence of the template element's content attribute.
if ("content" in document.createElement("template")) {
// Instantiate the table with the existing HTML tbody
// and the row with the template
const tbody = document.querySelector("tbody");
const template = document.querySelector("#productrow");
// Clone the new row and insert it into the table
const clone = document.importNode(template.content, true);
let td = clone.querySelectorAll("td");
td[0].textContent = "1235646565";
td[1].textContent = "Stuff";
tbody.appendChild(clone);
// Clone the new row and insert it into the table
const clone2 = document.importNode(template.content, true);
td = clone2.querySelectorAll("td");
td[0].textContent = "0384928528";
td[1].textContent = "Acme Kidney Beans 2";
tbody.appendChild(clone2);
} else {
// Find another way to add the rows to the table because
// the HTML template element is not supported.
}
В результате получаем исходную HTML-таблицу с двумя новыми строками, добавленными с помощью JavaScript:
Реализация декларативного теневого DOM
В этом примере в начале разметки находится скрытое предупреждение о поддержке. Если браузер не поддерживает атрибут shadowrootmode, предупреждение будет показано с помощью JavaScript. Далее идут два элемента <article>, каждый из которых содержит вложенные элементы <style> с разным поведением. Первый элемент <style> действует во всём документе. Область действия второго ограничена теневым корнем, созданным вместо элемента <template> благодаря наличию атрибута shadowrootmode.
<p hidden>
⛔ Your browser doesn't support <code>shadowrootmode</code> attribute yet.
</p>
<article>
<style>
p {
padding: 8px;
background-color: wheat;
}
</style>
<p>I'm in the DOM.</p>
</article>
<article>
<template shadowrootmode="open">
<style>
p {
padding: 8px;
background-color: plum;
}
</style>
<p>I'm in the shadow DOM.</p>
</template>
</article>
const isShadowRootModeSupported = Object.hasOwn(
HTMLTemplateElement.prototype,
"shadowRootMode",
);
document
.querySelector("p[hidden]")
.toggleAttribute("hidden", isShadowRootModeSupported);
Декларативный теневой DOM с делегированием фокуса
В этом примере показано, как shadowrootdelegatesfocus применяется к теневому корню, созданному декларативно, и как это влияет на фокус.
Сначала в коде внутри элемента <div> объявляется теневой корень с помощью элемента <template> и атрибута shadowrootmode. В нём отображаются нефокусируемый элемент <div> с текстом и фокусируемый элемент <input>. Кроме того, с помощью CSS элементы с :focus окрашиваются в синий цвет, а для элемента-хоста задаются обычные стили.
<div>
<template shadowrootmode="open">
<style>
:host {
display: block;
border: 1px dotted black;
padding: 10px;
margin: 10px;
}
:focus {
outline: 2px solid blue;
}
</style>
<div>Clickable Shadow DOM text</div>
<input type="text" placeholder="Input inside Shadow DOM" />
</template>
</div>
Второй блок кода идентичен первому, за исключением того, что в нём задан атрибут shadowrootdelegatesfocus. Если выбран нефокусируемый элемент дерева, этот атрибут передаёт фокус первому фокусируемому элементу дерева.
<div>
<template shadowrootmode="open" shadowrootdelegatesfocus>
<style>
:host {
display: block;
border: 1px dotted black;
padding: 10px;
margin: 10px;
}
:focus {
outline: 2px solid blue;
}
</style>
<div>Clickable Shadow DOM text</div>
<input type="text" placeholder="Input inside Shadow DOM" />
</template>
</div>
Наконец, используем следующий CSS, чтобы добавить красную рамку родительскому элементу <div>, когда он находится в фокусе.
div:focus {
border: 2px solid red;
}
Результаты показаны ниже. При первоначальном отображении HTML у элементов нет стилей, как показано на первом изображении. Если для теневого корня не задан shadowrootdelegatesfocus, можно щёлкнуть в любом месте, кроме <input>, и фокус не изменится (если выбрать элемент <input>, результат будет выглядеть как на втором изображении).
Если для теневого корня задан shadowrootdelegatesfocus, щелчок по тексту (который не может получить фокус) выбирает элемент <input>, поскольку он является первым фокусируемым элементом дерева. В результате родительский элемент также получает фокус, как показано ниже.
Декларативный теневой DOM с распределением по именованным слотам
В этом примере показано, как элементы распределяются по слотам теневого DOM на основе их атрибута slot (который сопоставляется с атрибутом name слота).
HTML
Сначала определим элемент <article>, содержащий заголовок, метаданные и текст статьи.
В статье находится элемент <template>, который станет теневым корнем благодаря атрибуту shadowrootmode. Атрибут shadowrootslotassignment задавать не нужно, поскольку распределение по именованным слотам используется по умолчанию.
Шаблон определяет элементы с именованными слотами для информации «header» и «meta», а также безымянный слот для информации «body». Для удобства различения элементы оформлены по-разному.
<article id="host">
<template shadowrootmode="open" shadowrootslotassignment="named">
<style>
.header {
background-color: plum;
}
.meta {
background-color: green;
}
.body {
background-color: lightblue;
}
</style>
<h2 class="header">
<slot name="title"></slot>
</h2>
<div class="meta">
<slot name="meta"></slot>
</div>
<div class="body">
<slot></slot>
</div>
</template>
<p>
Text 1 with no slot attribute. Goes into default (unnamed) slot inside the
"body" div.
</p>
<span slot="title">Text for the title slot</span>
<span slot="meta">Text for the meta slot</span>
<p>
Text 2 with no slot attribute. Also goes into default (unnamed) slot inside
the "body" div.
</p>
</article>
Внутри того же хоста, ниже шаблона, находятся четыре элемента для заполнения слотов. У элементов <span> есть атрибуты slot, соответствующие атрибутам name слотов в шаблоне, поэтому они заполняют соответствующие слоты. У двух элементов <p> нет имени, поэтому оба они вставляются в безымянный <slot> внутри элемента «body».
Результат
В примере ниже содержимое слотов должно отображаться в соответствующих разделах.
Декларативный теневой DOM с ручным распределением по слотам
В этом примере показано, как вручную распределять элементы по слотам теневого DOM.
При таком подходе каждый элемент нужно вручную назначить определённому слоту. Назначение по умолчанию отсутствует, поэтому любой неназначенный слот останется пустым.
HTML
Сначала добавим скрытое предупреждение о поддержке. Если браузер не поддерживает атрибут shadowrootslotassignment, предупреждение будет показано с помощью JavaScript.
<p id="support-warning" hidden> ⛔ Your browser doesn't support the <code>shadowrootslotassignment</code> attribute yet. </p>
Далее определим элемент <article>, содержащий заголовок, метаданные и текст статьи. В нём есть элемент <template>, который станет теневым корнем благодаря атрибуту shadowrootmode и будет использовать ручное распределение по слотам, поскольку задано значение shadowrootslotassignment="manual".
Шаблон определяет элементы со слотами для информации «header», «meta» и «body», на которые можно ссылаться по атрибуту id. Для удобства различения элементы оформлены по-разному.
<article id="host">
<template shadowrootmode="open" shadowrootslotassignment="manual">
<style>
.header {
background-color: plum;
}
.meta {
background-color: green;
}
.body {
background-color: lightblue;
}
</style>
<h2 class="header">
<slot id="titleSlot"></slot>
</h2>
<div class="meta">
<slot id="metaSlot"></slot>
</div>
<div class="body">
<slot id="bodySlot"></slot>
</div>
</template>
<span id="text_title">Text for the title slot</span>
<span id="text_meta">Text for the meta slot</span>
<p id="text_body_1">Text 1 for body slot.</p>
<p id="text_body_2">Text 2 for body slot.</p>
</article>
Внутри того же хоста, ниже шаблона, находятся четыре элемента для заполнения слотов. Они также идентифицируются по id.
JavaScript
Ниже показан JavaScript-код для ручного распределения по слотам. Сначала код получает слоты внутри теневого корня, затем текст для вставки и, наконец, назначает текст слоту. Обратите внимание: каждый узел можно назначить определённому слоту только один раз. Если назначить одному слоту несколько узлов с помощью HTMLSlotElement.assign(), порядок их указания определяет порядок вставки.
const host = document.querySelector("#host");
const shadow = host.shadowRoot;
// 1. Target your slots
const titleSlot = shadow.querySelector("#titleSlot");
const metaSlot = shadow.querySelector("#metaSlot");
const bodySlot = shadow.querySelector("#bodySlot");
// 2. Target the Elements to slot
const body1Text = document.querySelector("#text_body_1");
const body2Text = document.querySelector("#text_body_2");
const titleText = document.querySelector("#text_title");
const metaText = document.querySelector("#text_meta");
// 3. Manually assign them
titleSlot.assign(titleText);
metaSlot.assign(metaText);
bodySlot.assign(body2Text, body1Text);
Если распределение по слотам не поддерживается, код выводит скрытое предупреждение о поддержке.
const isShadowRootSlotAssignmentSupported = Object.hasOwn(
HTMLTemplateElement.prototype,
"shadowRootSlotAssignment",
);
document
.querySelector("p[hidden]")
.toggleAttribute("hidden", isShadowRootSlotAssignmentSupported);
Результат
В примере ниже содержимое слотов должно отображаться в соответствующих разделах.
Примечание: Если атрибут shadowrootslotassignment не поддерживается, отображается предупреждение, а браузер использует named распределение. Однако, поскольку ни у слотов, ни у вставляемых элементов нет имён, все элементы будут вставлены в слот заголовка (поскольку это первый безымянный слот и, следовательно, «слот по умолчанию»).
Данные DocumentFragment не клонируются
Когда передаётся значение DocumentFragment, метод Node.appendChild и аналогичные методы перемещают в целевой узел только дочерние узлы этого значения. Поэтому обычно предпочтительнее добавлять обработчики событий к дочерним узлам DocumentFragment, а не к самому DocumentFragment.
Рассмотрим следующий HTML и JavaScript:
HTML
<div id="container"></div> <template id="template"> <div>Click me</div> </template>
JavaScript
const container = document.getElementById("container");
const template = document.getElementById("template");
function clickHandler(event) {
event.target.append(" — Clicked this div");
}
const firstClone = document.importNode(template.content, true);
firstClone.addEventListener("click", clickHandler);
container.appendChild(firstClone);
const secondClone = document.importNode(template.content, true);
secondClone.children[0].addEventListener("click", clickHandler);
container.appendChild(secondClone);
Результат
Поскольку firstClone — это DocumentFragment, при вызове appendChild в container добавляются только дочерние узлы; обработчики событий firstClone не копируются. Напротив, поскольку обработчик событий добавлен к первому дочернему узлу secondClone, при вызове appendChild обработчик копируется, и щелчок по нему работает ожидаемым образом.
Техническая сводка
| Категории содержимого | метаданные, потоковое содержимое, фразовое содержимое, элемент, поддерживающий скрипты |
|---|---|
| Допустимое содержимое | Отсутствует (см. примечания по использованию) |
| Пропуск тегов | Не допускается: открывающий и закрывающий теги обязательны. |
| Допустимые родители | Любой элемент, допускающий содержимое метаданных, фразовое содержимое или элементы, поддерживающие скрипты. Также допускается в качестве дочернего элемента <colgroup>, у которого нет атрибута span. |
| Неявная роль ARIA | Соответствующая роль отсутствует |
| Допустимые роли ARIA | Роль role не допускается |
| Интерфейс DOM | HTMLTemplateElement |
Спецификации
| Спецификация |
|---|
| HTML> # the-template-element> |
Совместимость с браузерами
| Компьютеры | Мобильные устройства | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | WebView on iOS | |
template |
26 | 13 | 22 | 15 | 8 | 26 | 22 | 14 | 8 | 1.5 | 4.4 | 8 |
shadowrootclonable |
124 | 124 | 125 | 110 | 17.5 | 124 | 125 | 82 | 17.5 | 27.0 | 124 | 17.5 |
shadowrootcustomelementregistry |
146 | 146 | Нет | 130 | 26 | 146 | Нет | 97 | 26 | Нет | 146 | 26 |
shadowrootdelegatesfocus |
123 | 123 | 123 | 109 | 16.4 | 123 | 123 | 82 | 16.4 | 27.0 | 123 | 16.4 |
shadowrootmode |
11190–111 | 11190–111 | 123 | 9776–97 | 16.4 | 11190–111 | 123 | 7564–75 | 16.4 | 22.015.0–22.0 | 11190–111 | 16.4 |
shadowrootreferencetarget |
133 | 133 | 144 | 118 | 26 | 133 | Нет | Нет | 26 | Нет | Нет | Нет |
shadowrootserializable |
125 | 125 | Нет | 111 | 18 | 125 | Нет | 83 | 18 | 27.0 | 125 | 18 |
shadowrootslotassignment |
Нет | Нет | 151 | Нет | Нет | Нет | 151 | Нет | Нет | Нет | Нет | Нет |
См. также
-
partиexportpartsатрибуты HTML -
<slot>элемент HTML -
:has-slotted,:host,:host()и:host-context()псевдоклассы CSS -
::partи::slottedпсевдоэлементы CSS -
ShadowRootинтерфейс - Использование шаблонов и слотов
- Область действия CSS модуль
- Декларативный Shadow DOM (с HTML) в разделе Использование Shadow DOM
- Декларативный Shadow DOM на web.dev (2023)
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/template