Copyright © 2013 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. W3C liability, trademark and document use rules apply.
This specification describes a method for declaring inert DOM subtrees in HTML and manipulating them to instantiate document fragments with identical contents.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document was published by the Web Applications Working Group as a First Public Working Draft. If you wish to make comments regarding this document, please send them to public-webapps@w3.org (subscribe, archives). All feedback is welcome.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
template
elementAll diagrams, examples, notes, are non-normative, as well as sections explicitly marked as non-normative. Everything else in this specification is normative.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in RFC2119. For readability, these words do not appear in all uppercase letters in this specification.
To help with layering and to avoid circular dependencies between various parts of specification, this document consists of three consecutive narratives:
In a sense, these parts can be viewed as math, which sets up the reasoning environment, physics, which is the theoretical reasoning about the concept, and mechanics, which is the is the practical application of this reasoning.
Any point, at which a conforming UA must make decisions about the state or reaction to the state of the conceptual model, is captured as algorithm. The algorithms are defined in terms of processing equivalence. The processing equivalence is a constraint imposed on the algorithm implementors, requiring the output of the both UA-implemented and the specified algorithm to be exactly the same for all inputs.
This document relies on the following specifications:
The following terms are used throughout the specification:
DocumentFragment
interfaceThis section is non-normative.
Modern web pages dynamically alter the contents of their documents (e.g. in response to user interaction or new data arriving from the server). It is common that such web pages are authored to require fragments of HTML which may be used in certain states and may require further modification before use, such as the insertion of values appropriate for the usage context.
HTML currently provides no mechanism for the declaration of markup fragments as prototypes, which are serialized and deserialized with the document, but not used until needed. Consequently, authors hide these fragments so that their content is available at runtime but is otherwise ignored by the browser. This is generally done either by authoring the fragment as:
The former has the primary drawback that the author must take care that the fragment not have side effects, such as loading resources with URLs that are not yet fully composed, while the latter has the primary drawback that it encourages run-time parsing (via innerHTML) of strings which include user-supplied data and thus become XSS attack surfaces. Neither approach has an effective way to declare fragments which contain elements at the top-level that are only allowed to occur as children of specific elements (e.g. <tr> or <td>).
This specification defines the HTML Template element, which allows for the declaration of document fragments which are unused by the document when loaded, but are parsed as HTML and are available at runtime for use by the web page.
The <template> element can be placed anywhere within the <head>, <body>, and <frameset> elements, and its contents can contain any content which could otherwise occur at any location within the <head>, <body>, and <frameset> elements. The content of templates are not a part of the document (they do not display, are not matched by querySelector, etc.) and are inactive (e.g. do not cause resources to load, scripts to run, media to play, etc.).
A template provides a method for declaring document fragments in HTML. The document fragment that is declared by a template is called template contents.
A template contents owner is a document which does not have a browsing context.
Every document has an associated template contents owner, which is initialized in a way that is equivalent to processing these steps:
The template contents must be a DocumentFragment whose node document is a template contents owner.
While parsing, the stack of open elements is said to have a template element in html scope if it has a template
element in the specific scope consisting of the following element types:
Parts marked template contents case in algorithms in the parser section are parts that only occur if there is a template element in html scope (the parser is presently parsing template contents).
Parts marked fragment or template contents case in algorithms in the parser section are parts that only occur if the parser was created for the purposes of the fragment parsing algorithm or if there is a template element in html scope (the parser is presently parsing template contents).
template
elementThe template
element represents a template.
html
element, the head element, the body element, or the frameset element.
interface HTMLTemplateElement : HTMLElement {
readonly attribute DocumentFragment content;
}
content
of type DocumentFragment
, read-onlyPrior to first access, the content
property must be initialized in a way that is equivalent to processing these steps:
When a template element's node document changes, the template element's content
DocumentFragment must be adopted into the new node document's template contents owner document.
Non-normative note: It is recommended that user agents implementing the template element prevent DOM hierarhcy cycles, including those which contain a reference (graph edge) from template element to the templates document fragment. When such a cycle would be created, it is recommended that the user agent throw a HierarchyRequestError.
The parsing of templates is defined as a set of additions to the HTML parsing algorithm. When parsing, the template
element is in the special category.
Initially, the stack of template insertion modes is empty. The stack grows downwards; the topmost value on the stack is the first one added to the stack, and the bottommost value of the stack is the one most recently added.
The current template insertion mode is the bottommost node in this stack.
Whenever the HTML parser is about to create an element for the token, if the current node is a template
element, the element must be created with its ownerDocument set to the template contents owner of the ownerDocument of the template
element.
Whenever the HTML parser is about to append a node to a template
element, the node must be appended to the template contents of the template
element instead.
As a result, the HTML parser will never place any nodes as direct children of a template
element.
When popping elements from the stack of open elements, a conforming UA must abort the following procedures when the current node is template
:
When a node is to be foster parented, the last template
element with no table
element is below it in the stack of open elements is the foster parent element (NOT the template's parent!) if there is such a template
element in the stack of open elements. Otherwise normal rules for foster parenting apply.
This prevents the HTML parser from "lifting" content outside of a template when a node is to be foster parented, aligning template behavior more closely with the HTML fragment parsing algorithm.
Just after the step labeled "Loop" in the algorithm to reset the insertion mode appropriately, add the following step:
template
element, then switch the insertion mode to the current template insertion mode and abort these steps.Modify the step which begins "If node is a head element..." to be:
head
element and node is the context element, then switch the insertion mode to "in body" ("in body"! not "in head") and abort these steps (fragment case). Otherwise, switch the insertion mode to "in head", and abort these steps.The following cases which were previously annotated as fragment case, can now be entered during normal parsing (i.e. not only in the fragment case) immediately following encountering a </template> token, and the annotation should be removed:
Add the following to the list of element types for the algorithm to have an element in table scope:
template
in the HTML namespace
Just before the A start tag whose tag name is "head" rule in the "in head" insertion mode, add the following rules:
Modify the rule in the in body insertion mode for encountering a "html" start tag
Parse error. If the stack of open elements has a template element in html scope then ignore the token (template contents case). Otherwise, for each attribute on the token, check to see if the attribute is already present on the top element of the stack of open elements. If it is not, add the attribute and its corresponding value to that element.
Modify the first clause of the rule in the in body insertion mode for encountering a "body" start tag:
If the second element on the stack of open elements is not a body
element, or, if the stack of open elements has only one node on it, or, if the stack of open elements has a template element in html scope then ignore the token. (fragment or template contents case)
Modify the first clause of the rule in the in body insertion mode for encountering a "frameset" start tag:
If the second element on the stack of open elements is not a body
element, or, if the stack of open elements has only one node on it then ignore the token. (fragment or template contents case)
Just before the Any other start tag rule in the "in body" insertion mode, add the following rule:
Modify the step 10 of the rule in the in body insertion mode for encountering an end tag whose tag name is one of "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u":
If the common ancestor node is a table, tbody, tfoot, thead, or tr element, then, foster parent whatever last node ended up being in the previous step, first removing it from its previous parent node if any.
If the common ancestor is a template
element, append whatever last node ended up being in the previous step to the template element's content
DocumentFragment, first removing it from its previous parent node if any.
Otherwise, append whatever last node ended up being in the previous step to the common ancestor node, first removing it from its previous parent node if any.
Modify the non-normative Note for the rule in the in table insertion mode for encountering a "table" start tag:
Parse error. Act as if an end tag token with the tag name "table" had been seen, then, if that token wasn't ignored, reprocess the current token.
The fake end tag token here can only be ignored in the fragment or template contents case.
Modify the first clause of the rule in the in table insertion mode for encountering a "table" end tag:
If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token. (fragment or template contents case)
Just before the Anything else rule in the "in table" insertion mode, add the following rule:
The "in table body" insertion mode is not modified because it defers to "in table" for "Anything else". Likewise, the "in caption" and "in cell" insertion modes are not modified because they defer to "in body".
The following modification only modifies this two cases as "fragment or template contents case"
Modify the first clause of the rule in the in table body insertion mode for encountering a "caption", "col", "colgroup", "tbody", "tfoot", "thead" start tag or a "table" end tag:
If the stack of open elements does not have a tbody
, thead
, or tfoot
element in table scope, this is a parse error. Ignore the token. (fragment or template contents case)
The following modifications only modify these two case as "fragment or template contents case"
Modify the first clause of the rule in the in row insertion mode for encountering a "tr" end tag:
If the stack of open elements does not have an element in table scope with the same tag name as the token, this is a parse error. Ignore the token. (fragment or template contents case)
Modify the first clause of the rule in the in row insertion mode for encountering a "caption", "col", "colgroup", "tbody", "tfoot", "thead", "tr" start tag or a "table" end tag:
Act as if an end tag with the tag name "tr" had been seen, then, if that token wasn't ignored, reprocess the current token.
The fake end tag token here can only be ignored in the fragment or template contents case.
Modify the parenthetical comment within the An end tag whose tag name is one of: "table", "tbody", "tfoot", "thead", "tr" rule in the "in cell" insertion mode, to be:
(which can only happen for "tbody", "tfoot" and "thead", when parsing template contents, or in the fragment case)
Modify the first clause of the rule in the "in column group" insertion mode for encountering a "colgroup" end tag to be:
If the current node is the root html
or a template
element then this is a parse error; ignore the token. (fragment or template contents case)
Just before the Anything else rule in the "in column group" insertion mode, add the following rule:
Just before the Anything else rule in the "in select" insertion mode, add the following rule:
Modify the first clause of the rule in the in frameset insertion mode for encountering a "frameset" end tag to be:
If the current node is the root html
, or, if the stack of open elements has a template element in html scope then this is a parse error; ignore the token. (fragment or template contents case)
Just before the Anything else rule in the "in frameset" insertion mode, add the following rule:
When the user is to apply the rules for the "template contents" insertion mode, the user agent must handle the token as follows:
html
element, then stop parsing. (fragment case)Add a sub-step to step 4 (If there is a context element) before sub-step 5 (Reset the parser's insertion mode appropriately):
If the context element is a template
element, push "template contents" onto the stack of template insertion modes.
The steps for cloning a node are defined by the DOM4 specification.
Add a step before step 7 (Return copy):
If the clone children flag is set and node is template
element, clone all the children of node's content and append them to copy's content, with ownerDocument set as node's template content owner and the clone children flag being set.
The serialization of templates is defined as the following addition to the Serializing HTML Fragments algorithm.
When running these steps, before step 2 ("For each child node of the node, in tree order, run the following steps"), insert the following step:
If the node is a <template> element, let the node be the DocumentFragment referenced by the node's content attribute
The behavior of innerHTML on templates is defined as a modification to the DOM Parsing and Serialization specification.
When running the steps for setting innerHTML, modify step 2, ("Replace all, with fragment within the context object") to be:
If context object is an HTML Template Element, replace all with fragment within the DocumentFragment referenced by the content object's content attribute. Otherwise, replace all with fragment within the context object.
The parsing of XHTML documents is defined as the following additions to Parsing XHTML documents.
When a user agent is contructing a DOM tree corresponding to the input passed to the XML parser, and a node is about to be appended to a template
element, the node must instead be appended to the template element's content
DocumentFragment. Also, when the user agent creates a node for insertion to the DOM tree, the created node's node document must be set to that of the element to which it will be appended.
The serialization of XHTML documents is defined as the following additions to Serializing XHTML documents.
When the algorithm must produce a serialization of a template
element, the string returned must be contain a serialization of the child nodes of the template element's content
DocumentFragment, rather than the template
element's children.
XSLT processing should to treat template contents as descendants of the template element when contained in XHTML input of an XSLT transform and place the descendants of a template element into template contents in XSLT output. However, XPath evaluation using the XPath DOM API should not to match on template contents.
The template contents are hidden implicitly since they are not part of the document. The template element itself must be hidden by default through the following addition to the user agent style sheet.
@namespace "http://www.w3.org/1999/xhtml";
template {
display : none;
}
The template
element was described by Ian Hickson in the XBL 2.0 specification, and this HTML Templates specification borrows most of semantics from there, applying them to the HTML realm.
Erik Arvidsson and Adam Klein worked closely with the editors to help identify requirements and use cases for the templates, producing the Model-driven Views library, which uses a template
element extensively.
The editors would also like to thank Adam Barth, Henri Sivonen, and Tab Atkins for their useful comments and contributions to the specification.