HTML Templates

W3C Working Draft 14 February 2013

This version
http://www.w3.org/TR/2013/WD-html-templates-20130214/
Latest version
http://www.w3.org/TR/html-templates/
Latest editor's draft
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html
Previous version
None
Revision history
https://dvcs.w3.org/hg/webcomponents/log/tip/spec/templates/index.html
Participate
Discuss on public-webapps@w3.org (Web Applications Working Group)
File bugs (w3.org's Bugzilla)
Editors
Dimitri Glazkov, Google, <>
Rafael Weinstein, Google, <>
Tony Ross, Microsoft, <>

Abstract

This specification describes a method for declaring inert DOM subtrees in HTML and manipulating them to instantiate document fragments with identical contents.

Status of This Document

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.

Table of Contents

  1. 1 About this Document
  2. 2 Dependencies
  3. 3 Terminology
  4. 4 Introduction
  5. 5 Definitions
  6. 6 The template element
  7. 7 Parsing HTML Templates
    1. 7.1 The stack of template insertion modes
    2. 7.2 Creating an element for a token
    3. 7.3 Appending to a template
    4. 7.4 Clearing the stack back to a given context
    5. 7.5 Additions to "foster parenting"
    6. 7.6 Additions to "reset the insertion mode appropriately"
    7. 7.7 Additions to "has an element in table scope"
    8. 7.8 Additions to the "in head" insertion mode
    9. 7.9 Additions to the "in body" insertion mode
    10. 7.10 Additions to the "in table" insertion mode
    11. 7.11 Additions to the "in table body" insertion mode
    12. 7.12 Additions to the "in row" insertion mode
    13. 7.13 Additions to the "in cell" insertion mode
    14. 7.14 Additions to the "in column group" insertion mode
    15. 7.15 Additions to the "in select" insertion mode
    16. 7.16 Additions to the "in frameset" insertion mode
    17. 7.17 The "template contents" insertion mode
  8. 8 Additions to the steps for parsing HTML fragments
  9. 9 Additions to the steps to clone a node
  10. 10 Serializing HTML Templates
  11. 11 innerHTML on Templates
  12. 12 Additions to Parsing XHTML Documents
  13. 13 Additions to Serializing XHTML Documents
  14. 14 Behavior of XSLT and XPath in the presence of the template element
  15. 15 Additions to the CSS user agent style sheet
  16. Acknowledgements

1 About this Document

All 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:

  1. setting up the stage for the specification,
  2. explaining of the conceptual model and algorithms behind it, and
  3. expressing this model with DOM interfaces and HTML elements.

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.

2 Dependencies

This document relies on the following specifications:

3 Terminology

The following terms are used throughout the specification:

context object
The object on which the method or attribute being discussed was called
DOM
The document object model
document
The Document Object Model's underlying document
node
Any DOM object that participates in a tree
document fragment
A DOM object that implements the DocumentFragment interface
element
A DOM object that implements the Element interface
DOM tree
Any tree, composed of DOM objects

4 Introduction

This 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.).

5 Definitions

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:

Input
DOCUMENT, the document
Output
TEMPLATE CONTENTS OWNER, the template contents owner
  1. If DOCUMENT does not have a browsing context, let TEMPLATE CONTENTS OWNER be DOCUMENT and abort these steps.
  2. Otherwise, let TEMPLATE CONTENTS OWNER be a new Document node that does not have a browsing context.
  3. If DOCUMENT is an HTML document, Mark TEMPLATE CONTENTS OWNER as an HTML document.

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).

6 The template element

The template element represents a template.

Context
As a descendant of the head element.
As a descendant of the body element.
As a descendant of the frameset element.
Content Model
Any, except the html element, the head element, the body element, or the frameset element.
Content attributes
Global attributes
DOM Interface

interface HTMLTemplateElement : HTMLElement {
    readonly attribute DocumentFragment content;
}
        
Attributes
content of type DocumentFragment, read-only
Provides access to template contents

Prior to first access, the content property must be initialized in a way that is equivalent to processing these steps:

Input
TEMPLATE, the template
Output
CONTENTS, the template contents
  1. Let DOCUMENT be the template contents owner of the node document of the context object.
  2. Let CONTENTS be a new DocumentFragment object whose node document is DOCUMENT and associated host element is TEMPLATE.

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.

7 Parsing HTML Templates

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.

7.1 The stack of template insertion modes

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.

7.2 Creating an element for the token

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.

7.3 Appending to a template

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.

7.4 Clearing the stack back to a given context

When popping elements from the stack of open elements, a conforming UA must abort the following procedures when the current node is template:

  1. Clearing the stack back to a table context
  2. Clearing the stack back to a table body context
  3. Clearing the stack back to a table row context

7.5 Additions to "foster parenting"

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.

7.6 Additions to "reset the insertion mode appropriately"

Just after the step labeled "Loop" in the algorithm to reset the insertion mode appropriately, add the following step:

  1. If node is a 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:

  1. If node is a 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:

7.7 Additions to "has an element in table scope"

Add the following to the list of element types for the algorithm to have an element in table scope:

7.8 Additions to the "in head" insertion mode

Just before the A start tag whose tag name is "head" rule in the "in head" insertion mode, add the following rules:

A start tag whose tag name is "template"
Run these steps:
  1. Insert a marker at the end of the list of active formatting elements
  2. Insert an HTML element for the token
  3. Switch the insertion mode to "template contents"
  4. Push "template contents" onto the stack of template insertion modes so that it is the new current template insertion mode.
An end tag whose name is "template"
If the stack of open elements does not have an element in scope with the same tag name as that of the token, then this is a parse error; ignore the token.
Otherwise, run these steps:
  1. Generate implied end tags
  2. If the current node is not an element with the same tag name as that of the token, then this is a parse error
  3. Pop elements from the stack of open elements until an element with the same tag name as the token has been popped from the stack
  4. Clear the list of active formatting elements up to the last marker
  5. Pop the current template insertion mode off the stack of template insertion modes.
  6. Reset the insertion mode appropriately

7.9 Additions to the "in body" insertion mode

Modify the rule in the in body insertion mode for encountering a "html" start tag

A start tag whose tag name is "html"

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:

A start tag whose tag name is "body"

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:

A start tag whose tag name is "frameset"

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:

A start tag whose tag name is "template"
An end tag whose name is "template"
Process the token using the rules for the "in head" insertion mode

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.

7.10 Additions to the "in table" insertion mode

Modify the non-normative Note for the rule in the in table insertion mode for encountering a "table" start tag:

A start tag whose tag name is "table"

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:

A end tag whose tag name is "table"

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:

A start tag whose tag name is "template"
An end tag whose name is "template"
Process the token using the rules for the "in head" insertion mode

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".

7.11 Additions to the "in table body" insertion mode

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:

A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "tfoot", "thead"
An end tag whose tag name is "table"

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)

7.12 Additions to the "in row" insertion mode

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:

A end tag whose tag name is "tr"

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:

A start tag whose tag name is one of: "caption", "col", "colgroup", "tbody", "tfoot", "thead", "tr"
An end tag whose tag name is "table"

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.

7.13 Additions to the "in cell" insertion mode

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)

7.14 Additions to the "in column group" insertion mode

Modify the first clause of the rule in the "in column group" insertion mode for encountering a "colgroup" end tag to be:

An end tag whose tag name is "colgroup"

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:

A start tag whose tag name is "template"
An end tag whose name is "template"
Process the token using the rules for the "in head" insertion mode

7.15 Additions to the "in select" insertion mode

Just before the Anything else rule in the "in select" insertion mode, add the following rule:

A start tag whose tag name is "template"
An end tag whose name is "template"
Process the token using the rules for the "in head" insertion mode

7.16 Additions to the "in frameset" insertion mode

Modify the first clause of the rule in the in frameset insertion mode for encountering a "frameset" end tag to be:

An end tag whose tag name is "frameset"

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:

A start tag whose tag name is "template"
An end tag whose name is "template"
Process the token using the rules for the "in head" insertion mode

7.17 The "template contents" insertion mode

When the user is to apply the rules for the "template contents" insertion mode, the user agent must handle the token as follows:

A character token
Process the token using the rules for the "in body" insertion mode.
A DOCTYPE token
Parse error. Ignore the token.
A comment token
A start tag whose name is one of: "link", "script", "style", "meta", template"
Process the token using the rules for the "in head" insertion mode.
A start tag whose name is "frame"
Pop the current template insertion mode off the stack of template insertion modes, push "in frameset" onto the stack of template insertion modes, switch the insertion mode to "in frameset" and reprocess the current token
A start tag whose name is "col"
Pop the current template insertion mode off the stack of template insertion modes, push "in column group" onto the stack of template insertion modes, switch the insertion mode to "in column group" and reprocess the current token
A start tag whose name is one of: "caption", "colgroup", "tbody", "tfoot", "thead"
Pop the current template insertion mode off the stack of template insertion modes, push "in table" onto the stack of template insertion modes, switch the insertion mode to "in table" and reprocess the current token
A start tag whose name is one of: "tr"
Pop the current template insertion mode off the stack of template insertion modes, push "in table body" onto the stack of template insertion modes, switch the insertion mode to "in table body" and reprocess the current token
A start tag whose name is one of: "td", "th"
Pop the current template insertion mode off the stack of template insertion modes, push "in row" onto the stack of template insertion modes, switch the insertion mode to "in row" and reprocess the current token
A start tag whose tag name is "template"
An end tag whose name is "template"
Process the token using the rules for the "in head" insertion mode
Any other start tag
Pop the current template insertion mode off the stack of template insertion modes, push "in body" onto the stack of template insertion modes, switch the insertion mode to "in body" and reprocess the current token
Any other end tag
Parse error. Ignore the token.
An end-of-file token
If the current node is the root html element, then stop parsing. (fragment case)
Otherwise, this is a parse error. Run these steps:
  1. Pop the current node off the stack of open elements
  2. Reset the insertion mode appropriately and reprocess the token

8 Additions to the steps for parsing HTML fragments

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.

9 Additions to the steps to clone a node

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.

10 Serializing HTML Templates

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

11 innerHTML on Templates

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.

12 Additions to Parsing XHTML Documents

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.

13 Additions to Serializing XHTML Documents

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.

14 Behavior of XSLT and XPath in the presence of the template element

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.

15 Additions to the CSS user agent style sheet

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;
}

Acknowledgements

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.

See a problem? Select text and or view bugs filed.