Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update template element description and add shadowrootmode attribute #31490

Merged
merged 18 commits into from
Jan 25, 2024
Merged
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 65 additions & 6 deletions files/en-us/web/html/element/template/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,37 @@ browser-compat: html.elements.template

{{HTMLSidebar}}

The **`<template>`** [HTML](/en-US/docs/Web/HTML) element is a mechanism for holding {{Glossary("HTML")}} that is not to be rendered immediately when a page is loaded but may be instantiated subsequently during runtime using JavaScript.
The **`<template>`** [HTML](/en-US/docs/Web/HTML) element is a mechanism for holding {{Glossary("HTML")}} fragments to be used later via JavaScript or immediately generated into shadow DOM:
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

Think of a template as a content fragment that is being stored for subsequent use in the document. While the parser does process the contents of the **`<template>`** element while loading the page, it does so only to ensure that those contents are valid; the element's contents are not rendered, however.
1. By default, the element's content is not rendered, only parsed into a [document fragment](/en-US/docs/Web/API/DocumentFragment). Using the {{domxref("HTMLTemplateElement.content", "content")}} property in JavaScript, this fragment could be cloned via {{domxref("Node.cloneNode", "cloneNode")}} method and inserted into the DOM.
2. If the `shadowrootmode` attribute is present, the HTML parser will immediately generate a shadow DOM. The element is replaced in the DOM by its content wrapped in a [shadow root](/en-US/docs/Glossary/Shadow_tree).
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

## Attributes

The only standard attributes that the `<template>` element supports are the [global attributes](/en-US/docs/Web/HTML/Global_attributes).
This element includes the [global attributes](/en-US/docs/Web/HTML/Global_attributes).

In Chromium-based browsers, the `<template>` element also supports a non-standard [`shadowrootmode` attribute](https://github.com/mfreed7/declarative-shadow-dom/blob/master/README.md#syntax), as part of an experimental ["Declarative Shadow DOM"](https://developer.chrome.com/docs/css-ui/declarative-shadow-dom) proposal. In supporting browsers, a `<template>` element with the `shadowrootmode` attribute is detected by the HTML parser and immediately applied as the shadow root of its parent element. `shadowrootmode` can take a value of `open` or `closed`; these are equivalent to the `open` and `closed` values of the {{domxref("Element.attachShadow()")}} `mode` option.
- `shadowrootmode`

Also, the corresponding {{domxref("HTMLTemplateElement")}} interface includes a standard {{domxref("HTMLTemplateElement.content", "content")}} property (without an equivalent content/markup attribute). This `content` property is read-only and holds a {{domxref("DocumentFragment")}} that contains the DOM subtree represented by the template. Be careful when using the `content` property because the returned `DocumentFragment` can exhibit unexpected behavior. For more details, see the [Avoiding DocumentFragment pitfalls](#avoiding_documentfragment_pitfalls) section below.
- : Creates a [shadow root](/en-US/docs/Glossary/Shadow_tree) for the parent element. A declarative version of the {{domxref("Element.attachShadow()")}} taking the same values:
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

- `open`

- : Exposes the internal shadow root DOM for JavaScript (recommended for most use cases).

- `closed`

- : Hides the internal shadow root DOM from JavaScript.

> **Note:** This is a feature of the HTML parser that cannot be used after the parsing by setting the `shadowrootmode` attribute via JavaScript. Only allowed values will create the shadow root. Empty or any other value won't trigger this behavior.
>
> You may find the non-standard `shadowroot` attribute in older tutorials and examples that used to be supported in Chrome 90-110. This attribute has been removed and replaced by the standard `shadowrootmode` attribute.
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

The corresponding {{domxref("HTMLTemplateElement")}} interface includes a standard {{domxref("HTMLTemplateElement.content", "content")}} property (without an equivalent content/markup attribute). This `content` property is read-only and holds a {{domxref("DocumentFragment")}} that contains the DOM subtree represented by the template. Be careful when using the `content` property because the returned `DocumentFragment` can exhibit unexpected behavior. For more details, see the [Avoiding DocumentFragment pitfalls](#avoiding_documentfragment_pitfalls) section below.
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

## Examples

### Table row generation
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

First we start with the HTML portion of the example.

```html
Expand Down Expand Up @@ -89,7 +106,48 @@ table td {
}
```

{{EmbedLiveSample("Examples", 500, 120)}}
{{EmbedLiveSample("Table row generation", 500, 120)}}

### Declarative shadow DOM
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

At the beginning of the markup, we have a hidden support warning that we will show later via JavaScript if the browser doesn't support the `shadowrootmode` attribute. After that, there are two {{HTMLElement("article")}} elements with nested {{HTMLElement("style")}} elements that behave differently. The first is global to the whole document, while the second is scoped to the shadow root generated in place of the `<template>` element because the `shadowrootmode` attribute is present.
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved

```html
<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>
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved
</template>
</article>
```

```js
const isShadowRootModeSupported =
HTMLTemplateElement.prototype.hasOwnProperty("shadowRootMode");

document
.querySelector("p[hidden]")
.toggleAttribute("hidden", isShadowRootModeSupported);
```

{{EmbedGHLiveSample("dom-examples/shadow-dom/shadowrootmode/scoping.html", "", "120")}}

## Avoiding DocumentFragment pitfalls

Expand Down Expand Up @@ -220,3 +278,4 @@ Since `firstClone` is a `DocumentFragment`, only its children are added to `cont
- [`ShadowRoot`]("/en-US/docs/Web/API/ShadowRoot) interface
- [Using templates and slots](/en-US/docs/Web/API/Web_components/Using_templates_and_slots)
- [CSS scoping](/en-US/docs/Web/CSS/CSS_scoping) module
- [Introduction to declarative shadow DOM](https://developer.chrome.com/docs/css-ui/declarative-shadow-dom)
pepelsbey marked this conversation as resolved.
Show resolved Hide resolved