Abstract

This specification describes a method of combining multiple DOM trees into one hierarchy and how these trees interact with each other within a document, thus enabling better composition of the DOM.

Status of This Document

This is a work in progress! This specification is for review and not for implementation! For the latest updates, including important bug fixes, please look at the draft on GitHub instead.

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 W3C Web Applications (WebApps) as a Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-webapps@w3.org (subscribe, archives). All comments are 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.

This document is governed by the 1 September 2015 W3C Process Document.

Table of Contents

1. Conformance

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

2.1 Shadow trees

A document tree is a node tree [DOM] whose root node is a document.

Any element can host zero or one associated node trees, called a shadow tree.

A shadow host is an element that hosts one shadow tree.

A shadow tree has an associated flag, called an encapsulation mode, which is either open or closed.

A shadow root is the root node of a shadow tree.

A node A is called a deep child of a node B, if either A is a child of B or A is the root node of the shadow tree that B hosts.

A node A is called a deep descendant of a node B, if either A is a deep child of B or A is a deep child of a node C that is a deep descendant of B.

An inclusive deep descendant is a node or one of its deep descendants.

A node A is called a deep parent of a node B if and only if B is a deep child of A.

A node A is called a deep ancestor of a node B if and only if B is a deep descendant of A.

An inclusive deep ancestor is a node or one of its deep ancestors.

When an element is an inclusive deep descendant of a document element, it is in a document deeply.

2.2 Trees of trees

A tree of trees is a tree of node trees.

Note

The purpose of introducing a tree of trees here is to define algorithms easily in the following sections. This is a kind of a notation techchique to make the this specification simpler.

Just like a node tree is defined as a set of relationships between nodes, a tree of trees is similarly defined as a set of relationships between node trees:

A node tree A is called an unclosed tree of a node tree B if and only if one, at least, of the following conditions is satisfied:

A node A is called an unclosed node of a node B if and only if the node tree that A participates in is an unclosed tree of the node tree that B participates in.

The ownerDocument property of a node in a shadow tree must refers to the document of the shadow host which hosts the shadow tree.

Window object named properties [HTML] must access the nodes in the document tree.

2.2.1 Example tree of trees

This section is non-normative.

Fig. 1 A tree of trees.

In the figure, there are six node trees, named A, B, C, D, E and F. The shadow trees, B, C and D, are hosted by elements which participate in the document tree A. The shadow trees, E and F, are hosted by elements which participates in the shadow tree D. The following set of relationships holds in the figure:

Note

As for a relationship between nodes, it's worth mentioning that there is no ancestor/descendant relationships between two nodes if they participate in different node trees. A shadow root is not a child node of the shadow host. The parent node of a shadow root doesn't exist. Because of this nature, most of existing APIs are scoped and don't affect other node trees, even though they are forming one tree of trees. For example, document.getElementById(elementId) never returns an element in a shadow tree, even when the element has the given elementId.

The same thing also applies to CSS Selectors matching. For example, a descendant combinator never descends into a node in a child shadow tree because a shadow root is not a child node of the shadow host. Unless a special CSS Selector for Shadow DOM, which is mentioned later, is used, a CSS Selector never matches an element in a different node tree.

Note

Because ShadowRoot inherits DocumentFragment, as specified later, you can use ShadowRoot.getElementByID(elementId) to get a node in the shadow tree.

2.3 Composed trees

A composed tree is a node tree which is constructed out of nodes from multiple node trees in a tree of trees. The exact algorithm of constructing a composed tree is specified later.

Fig. 2 A composed tree

A document composed tree is a composed tree whose root node is a document

A node is in a document composed tree if it participates in a document composed tree.

Unless an element is in a document composed tree, the element must not create any CSS box.

In resolving CSS inheritance, an element must inherit from the parent node in the composed tree, if applicable.

User agents must use the document composed tree in the visual formatting model, instead of the document tree.

Note

The editor's draft of CSS Scoping specification [css-scoping-1] defines the selectors which are related to Shadow DOM. Specifically, it defines the following selectors related to Shadow DOM:

  • ::shadow pseudo element
  • /deep/ combinator, which was replaced with a >>> combinator (or shadow piercing descendant combinator)
  • ::content pseudo-element
  • :host pseudo-class and :host() functional pseudo-class
  • :host-context() functional pseudo-class

3. Distributions

3.1 Slots

A slot is a defined location in a shadow tree into which some of a shadow host's children are inserted in its composed tree. The exact algorithm of constructing a composed tree is specified later.

A node can be assigned to a slot, called an assigned slot. The exact algorithm of determining the assigned slot for a node is specified later.

A distribution is the mechanism that determines which nodes appear at each slot. The exact algorithm of a distribution is specified later.

Fig. 3 A distribution

The slot element that satisfies the following condition defines a slot at the location of the element:

A slot name is the name of a slot.

A default slot is a slot whose slot name is the empty string or missing. If there are more than one slots which don't have a slot name in the same shadow tree, the most preceding one is the default slot. The others are not.

3.2 Slotting Algorithm

The slotting algorithm must be used to determine the assigned slot for a node and must be equivalent to processing the following steps:

Input
NODE, a node
Output
(nullable) SLOT, a slot to where NODE is assigned.
  1. If the parent node of NODE is a shadow host:
    1. Let TREE be the shadow tree that the parent node of NODE hosts
    2. Let NAME be the value of the slot attribute of NODE
    3. If NAME is the empty string or missing:
      1. Let SLOT be a default slot for TREE if it exits, Otherwise, null
    4. Otherwise:
      1. Let SLOT be the most preceding slot in TREE whose slot name is NAME if it exists. Otherwise null.
  2. Otherwise:
    1. Let SLOT be null

3.3 Distributed Nodes Algorithm

The get distributed nodes algorithm must be used to determine the distributed nodes for a slot and must be equivalent to processing the following steps:

Input
SLOT, a slot
Output
DISTRIBUTED-NODES, an ordered list of nodes.
  1. Let HOST be a shadow host which hosts a shadow tree that SLOT participates in
  2. For each child node NODE of HOST:
    1. If NODE is assinged to SLOT:
      1. If NODE is a slot:
        1. Let SUB-LIST be the result of (recursively) running the get distributed nodes algorithm with NODE as input
        2. Append all nodes in SUB-LIST to DISTRIBUTED-NODES
      2. Otherwise:
        1. Append NODE to DISTRIBUTED-NODES

4. Composition

4.1 Composition Algorithm

The composed tree children calculation algorithm must be used to determine the child nodes of a node in the composed tree and must be equivalent to processing the following steps:

Input
NODE, a node which participates in a composed tree
Output
CHILDREN, the child nodes of NODE in the composed tree.
  1. Let CHILDREN be an empty ordered list of nodes
  2. If NODE is a shadow host:
    1. Let CHILD-POOL be the child nodes of the shadow root which NODE hosts
  3. Otherwise:
    1. Let CHILD-POOL be the child nodes of NODE
  4. For each node, CHILD, in CHILD-POOL:
    1. If CHILD is a slot:
      1. If CHILD is not assigned to any slot:
        1. Append all nodes of the distributed nodes of CHILD to CHILDREN
    2. Otherwise:
      1. Append CHILD to CHILDREN

For a given tree of trees TREE-OF-TREES, the composed tree constructed from TREE-OF-TREES must be equivalent to the following tree:

4.2 Composition Example

This section is non-normative.

Suppose that we have the following tree of trees:

Fig. 4 An example tree of trees. A node whose color is red represents a slot. Unlike the previous figures, a box surrounding a node tree is omitted here.

This tree of trees is composed of the following 3 node trees, one document tree and two shadow trees:

Node tree Root node is: Hosted by: Composed of: (in tree order)
document tree 1 A - A, B, C, D, E, F, G, H, I
shadow tree 1 J C J, K, L, M, N, O, P, Q
shadow tree 2 R N R, S, T

Suppose that an assigned slot for each node, if it exists, is:

Fig. 5 A result of slotting.

Then, the distributed nodes for each slot will be:

Node tree Root node is: Hosted by: Composed of: (in tree order) Assigned Slot for a node Distributed nodes for a slot
document tree 1 A - A, B, C, D, E, F, G, H, I (D => L), (F => L), (H => O) -
shadow tree 1 J C J, K, L, M, N, O, P, Q (O => T), (P => T) L <= [D, F], M <= [], O <= [H]
shadow tree 2 R N R, S, T - T <= [H, P]
Note
  • More than one nodes can be assigned to the same slot. e.g. (D => L), (F => L)
  • A slot can be assigned to an other slot, e.g. (O => T)
  • The distributed nodes for T are [H, P]. That aren't [O, P]. A slot is never a member of distributed nodes of an other slot. If a slot A is assigned to an other slot B, the distributed nodes for A are appended to the distributed nodes for B, instead of A itself, as per the get distributed nodes algorithm.

The document composed tree will be:

Fig. 6 Document composed tree.
Note
  • A slot never participates in a document composed tree. Neither a shadow root does.
  • Node G doesn't participate in the document composed tree. G is a child of a shadow host, but it's not assigned to any slot.
  • In an extreme case, even if a document tree has more than 1,000 nodes, you can make the page *blank* by attaching a shadow root to the document element because a document composed tree is used in rendering.

5. Events

In each algorithm in this section, the Window must be considered as if it were the parent node of the Document so that the Window also receives an event.

When an event is dispatched in a shadow tree, its path either crosses the shadow trees or is terminated at the shadow root. One exception are the mutation events. The mutation event types must never be dispatched in a shadow tree.

5.1 Events that are not leaked into ancestor trees

For the following events, scoped flag is initialized to true by default if the events are dispatched by the user agent:

Issue 1

Upstream this section into relevant specs, instead of having a fixed list here.

5.2 Event Paths

The event path calculation algorithm must be used to determine event path and must be equivalent to processing the following steps:

Input
NODE, a node
EVENT, an event
Output
PATH, an event path, a ordered list of an event target
  1. Let PATH be the empty ordered list of nodes
  2. Let CURRENT be NODE
  3. Repeat while CURRENT exists:
    1. Append CURRENT to PATH
    2. If all of the following conditions are satisfied, stop this algorithm:
      1. CURRENT is a shadow root
      2. CURRENT is the root node of NODE
      3. EVENT's scoped flag is set
    3. If CURRENT is assigned to a slot SLOT:
      1. Let CURRENT be SLOT
    4. Otherwise:
      1. Let CURRENT be the deep parent of CURRENT
Note

For a trusted event that has a relatedTarget attribute, the event path would be trimmed. See the event path trimming algorithm, which is specified later.

5.3 Event Paths Example

This section is non-normative.

Let's re-use the same tree of trees used in the composition example section. Suppose that an event is dispatched on node I. The event path will be:

[I, H, O, T, S, R, N, J, C, A] (Window is omitted)

It's worth pointing out that if we exclude all nodes which don't participate in the composed tree from the event path, the result would be equivalent to the inclusive ancestors of the node I in the composed tree.

Fig. 7 The relationship between the composed tree and an event path. If we exclude O, T, R and J, that don't participate in the composed tree, from the event path, the result would be equivalent to the inclusive ancestors of the node, I, in the composed tree.

Note that the event path calculation algorithm is designed to achieve the following goals:

  1. If there is a node, CHILD, in the event path and CHILD has a parent node, PARENT, in the node tree, the event path always includes PARENT. PARENT always appears somewhere after CHILD in the event path.
  2. Nodes in the event path form a linear ancestor chain in each node tree. There are no branch points in each node tree.
>
Fig. 8 The relationship between an event path and node trees. In the figure, a number shown in a right-side of each node represents a zero-based position of each node in the event path. A parent node always has a larger number than that of its child node in each node tree.

A local event path for each node tree would be seen as:

Node tree Local Event Path
document tree 1 [I, H, C, A]
shadow tree 1 [O, N, J]
shadow tree 2 [T, S, R]

That means, if your concern is only one node tree, you can forget all other node trees. The event path would be seen as if the event happened only on the node tree you are focusing on. This is an important aspect in a sense that hosting a shadow tree doesn't have any effect to the local event path as long as the event is not stopped somewhere in the descendant trees.

If you are a web author and your concern is only a document tree, this might be a good news because an event listener that is registered somewhere on the document tree would continue to work even when you attach a shadow root to an element in the document tree to enhance the element. At the same time, an author of a shadow tree also can receive an event which will happen on a node in the document tree, if the node, or its ancestor, is assigned to a slot in the shadow tree.

5.4 Event Retargeting

In the cases where event path is across multiple node trees, the event's information about the target of the event is adjusted in order to maintain encapsulation. Event retargeting is a process of computing relative targets for each ancestor of the node at which the event is dispatched. A relative target is a node that most accurately represents the target of a dispatched event at a given ancestor while maintaining the encapsulation.

The retargeting algorithm is used to determine relative targets and must be equivalent to processing the following steps:

Input
BASE, a base node for which a target node should be adjusted
TARGET, a target node which should be adjusted
Output
RELATIVE-TARGET, a relative target, the result of adjusting TARGET for BASE
  1. Let BASE-TREE be the node tree which BASE participates in
  2. Let TARGET-TREE be the node tree which TARGET participates in
  3. If BASE-TREE and TARGET-TREE participate in the same tree of trees:
    1. Let COMMON-ANCESTOR-TREE be the lowest common inclusive ancestor tree of BASE-TREE and TARGET-TREE
  4. Otherwise:
    1. Let COMMON-ANCESTOR-TREE be the root tree of TARGET-TREE
  5. For each node, ANCETOR, in an inclusive deep ancestor nodes of TARGET, from descendants to ancestors:
    1. If ANCESTOR participates in COMMON-ANCESTOR-TREE:
      1. Let RELATIVE-TARGET be ANCESTOR
      2. Stop this algorithm

The value of the Event object's target attribute must be the result of the retargeting algorithm with the event's currentTarget and target as input.

The event target retargeting process must occur prior to dispatch of an event.

5.5 Retargeting relatedTarget

Some events have a relatedTarget [DOM-Level-3-Events] property, which holds a node that's not the event's target, but is related to the event.

For instance, a mouseover event's relatedTarget may hold the node from which the mouse has moved to event's target. In the case where relatedTarget is in a shadow tree, the conforming UAs must not leak its actual value outside of this tree.

The value of the Event object's relatedTarget attribute must be the result of the retargeting algorithm with the event's currentTarget and relatedTarget as input. The result is called a relative related target.

The event relatedTarget retargeting process must occur prior to dispatch of an event.

5.6 Retargeting Touch Events

The Touch target [TOUCH-EVENTS] attribute must be adjusted in the same way as an event with a relatedTarget. Each Touch target in the TouchList returned from TouchEvent touches(), changedTouches() and targetTouches() must be the result of the retargeting algorithm with a current target and Touch target as input.

5.7 Retargeting Focus Events

The focus, focusin, blur, and focusout events must be treated in the same way as events with a relatedTarget, where the corresponding node that is losing focus as a result of target gaining focus or the node that is gaining focus, and thus causing the blurring of target acts as the related target.

5.8 Event Path Trimming

In cases where both relatedTarget and target of a trusted event are part of the same shadow tree, the conforming UAs must stop events at the shadow root to avoid the appearance of spurious mouseover and mouseout events firing from the same node.

Thus, event listeners for trusted events must not be invoked on a node for which the target and relatedTarget are the same.

The event path trimming algorithm must be used to trim the event path for a trusted event that has a relatedTarget attribute and must be equivalent to processing the following steps:

Input
EVENT-PATH, the event path, which is the result of the event path calculation algorithm
Output
EVENT-PATH is trimmed so that event listeners aren't invoked on a node for which the target and relatedTarget are the same.
  1. For each object, A, in EVENT-PATH:
    1. Let RELATIVE-TARGET be the relative target for A
    2. Let RELATIVE-RELATED-TARGET be the relative related target for A
    3. If RELATIVE-TARGET and RELATIVE-RELATED-TARGET are the same, remove A from EVENT-PATH.
Note

For an untrusted event, the event path trimming algorithm is not used.

5.9 Event Dispatch

At the time of event dispatch:

Upon completion of the event dispatch, the Event object's target and relatedTarget must be to the highest ancestor's relative target. Since it is possible for a script to hold on to the Event object past the scope of event dispatch, this step is necessary to avoid revealing the nodes in shadow trees.

5.10 Event Retargeting Example

This section is non-normative.

Suppose we have a user interface for a media controller, represented by this tree, composed of both document tree and the shadow trees. In this example, we will assume that selectors are allowed to cross the shadow boundaries and we will use these selectors to identify the elements. Also, we will invent a fictional shadow-root element to demarcate the shadow boundaries and represent shadow roots:

Example 1
<div id="player">
    <shadow-root id="player-shadow-root">
        <div id="controls">
            <button id="play-button">PLAY</button>
            <input type="range" id="timeline">
                <shadow-root id="timeline-shadow-root">
                    <div id="slider-thumb" id="timeline-slider-thumb"></div>
                </shadow-root>
            </input>
            <div id="volume-slider-container">
                <input type="range" id="volume-slider">
                    <shadow-root id="volume-shadow-root">
                        <div id="slider-thumb" id="volume-slider-thumb"></div>
                    </shadow-root>
                </input>
            </div>
        </div>
    </shadow-root>
</div>

Let's have a user position their pointing device over the volume slider's thumb (#volume-slider-thumb), thus triggering a mouseover event on that node. For this event, let's pretend it has no associated relatedTarget.

Per the retargeting algorithm, we should have the following set of ancestors and relative targets:

Ancestor Relative Target
#player #player
#player-shadow-root #volume-slider
#controls #volume-slider
#volume-slider-container #volume-slider
#volume-slider #volume-slider
#volume-shadow-root #volume-slider-thumb
#volume-slider-thumb #volume-slider-thumb

After we dispatch the mouseover event using these newly computed relative targets, the user decides to move their pointing device over the thumb of the timeline (#timeline-slider-thumb). This triggers both a mouseout event for the volume slider thumb and the mouseover event for the timeline thumb.

Let's see how the relatedTarget value of the volume thumb's mouseout event is affected. For this event, the relatedTarget is the timeline thumb (#timeline-slider-thumb). Per the relatedTarget retargeting, we should have the following set of ancestors and adjusted related targets:

Ancestor Relative Target Adjusted related Target
#player #player #player
#player-shadow-root #volume-slider #timeline
#controls #volume-slider #timeline
#volume-slider-container #volume-slider #timeline
#volume-slider #volume-slider #timeline
#volume-shadow-root #volume-slider-thumb #timeline
#volume-slider-thumb #volume-slider-thumb #timeline

The node, #player, has both target and relatedTarget being the same value (#player), which means that we do not dispatch the event on this node and its ancestors.

6. User Interaction

6.1 Ranges and Selections

This section is non-normative.

Selection [EDITING] is not defined. Implementation should do their best to do what's best for them. Here's one possible, admittedly naive way:

Since nodes which are in the different node trees never have the same root, there may never exist a valid DOM range that spans multiple node trees.

Accordingly, selections may only exist within one node tree, because they are defined by a single range. The selection, returned by the window.getSelection() method never returns a selection within a shadow tree.

The getSelection() method of the shadow root object returns the current selection in this shadow tree.

6.2 Focus Navigation

If a node doesn’t participate in the document composed tree, the node must be skipped from the sequential focus navigation.

The sequential focus navigation order for a given shadow tree A must be inserted into the sequential focus navigation order for the parent tree B as follows:

  1. Let HOST be the shadow host which hosts A
  2. The sequential focus navigation order for A must be inserted into the sequential focus navigation order for B:
    1. immediately after HOST, if HOST is focusable; or
    2. in place of the HOST as if HOST were assigned the tabindex value 0 for determining its position.

For directional focus navigation [CSS3-UI], it is up to the user agent to integrate the shadow trees into the document's directional focus navigation.

6.3 Active Element

To maintain encapsulation, the value of the Document object's focus API property activeElement must be adjusted. To prevent loss of information when adjusting this value, each shadow root must also have an activeElement property to store the value of the focused element in the shadow tree.

The active element adjustment algorithm must be used to determine the value of activeElement property, and it must be equivalent to processing the following steps:

Input
ROOT, either a document or a shadow root
ELEMENT, the focused element
Output
ADJUSTED, an adjusted activeElement property of ROOT.
  1. Let ADJUSTED be the result of the retargeting algorithm with ROOT and ELEMENT as input

6.4 Editing

The value of the contenteditable attribute must not propagate from shadow host to its shadow trees.

6.5 Assistive Technology

User agents with assistive technology traverse the composed tree, and thus enable full use of WAI-ARIA [WAI-ARIA] semantics in the shadow trees.

6.6 Hit Testing

When a text node is a child node of a shadow root, a hit testing must target the shadow host if the text node is the result of the hit testing.

User-agent mouse events must be targeted to the parent node in the composed tree of a text node if the topmost event target is the text node.

Note

This section eventually needs to be part of some general hit testing specification.

7. HTML Elements in Shadow Trees

7.1 Inertness of HTML Elements in a shadow tree

Comparatively, a shadow tree can be seen as somewhere between just part of a document and itself being a document fragment. Since it is rendered, a shadow tree aims to retain the traits of a typical tree in a document. At the same time, it is an encapsulation abstraction, so it has to avoid affecting the document tree. Thus, the HTML elements must behave as specified [HTML] in the shadow trees, with a few exceptions.

Note

According to the [HTML], some HTML Elements would have different behavior if they participate in a shadow tree, instead of a document tree, because their definitions require the elements to be in a document as a necessary condition for them to work. In other words, they shouldn't work if they participate in a shadow tree, even when they are in a document deeply. We must fill this gap because we expect that most of HTML Elements behave in the same way as in a document, as long as they are in a document deeply. See W3C Bug 26365 and Bug 27406 for the details. The following is the tentative summary of the discussions in the W3C bugs. We, however, haven't covered all HTML Elements and their behaviors here yet. For HTML Elements which are not explicitly stated here, they should be considered as active in a shadow tree. We are trying to update [HTML] itself, instead of having monkey patches here.

HTML Elements are classified into the following categories:

7.2 Attributes

When [HTML] defines the processing algorithms to traverse trees for the following attributes, they must use the composed tree.

Note

This list does not include attributes that are defined elsewhere in this specification. Such attributes include:

8. Elements and DOM interfaces

8.1 The ShadowRoot interface

The ShadowRoot interface represents the shadow root.

interface ShadowRoot : DocumentFragment {
    Selection?        getSelection ();
    Element?          elementFromPoint (double x, double y);
    sequence<Element> elementsFromPoint (double x, double y);
    CaretPosition?    caretPositionFromPoint (double x, double y);
    readonly    attribute Element?       activeElement;
    readonly    attribute Element        host;
    [TreatNullAs=EmptyString]
                attribute DOMString      innerHTML;
    readonly    attribute StyleSheetList styleSheets;
};

8.1.1 Attributes

activeElement of type Element, readonly , nullable

Represents the currently focused element in the shadow tree.

On getting, the attribute must return the currently focused element in the shadow tree or null, if there is none.

host of type Element, readonly

Represents the shadow host which hosts the context object.

On getting, the attribute must return the shadow host which hosts the context object.

innerHTML of type DOMString,

Represents the markup of ShadowRoot's contents.

On getting, the attribute must return the result of running the HTML fragment serialization algorithm with the context object as shadow host.

On setting, these steps must be run:

  1. Let FRAGMENT be the result of invoking the fragment parsing algorithm [DOM-PARSING] with the new value as MARKUP, and the context object as shadow host
  2. Replace all with FRAGMENT within the shadow root.
styleSheets of type StyleSheetList, readonly

Represents the shadow root style sheets.

On getting, the attribute must return a StyleSheetList sequence containing the shadow root style sheets.

8.1.2 Methods

caretPositionFromPoint
Note

It could be defined in roughly the same way as caretPositionFromPoint [CSSOM-VIEW]. Eventually, this needs to be part of CSSOM View Module specification [CSSOM-VIEW]. See also W3C bug 27829.

ParameterTypeNullableOptionalDescription
xdouble
ydouble
Return type: CaretPosition, nullable
elementFromPoint

Returns an element at specified coordinates.

Note

Eventually, this needs to be part of CSSOM View Module specification [CSSOM-VIEW]. See also W3C bug 27829.

When invoked, it must return result of running the following steps:

  1. If context object is not a ShadowRoot instance, throw an InvalidNodeTypeError.
  2. If either argument is negative, x is greater than the viewport width excluding the size of a rendered scroll bar (if any), or if y is greater than the viewport height excluding the size of a rendered scroll bar (if any), return null.
  3. Let HIT be the element at coordinates x and y in the viewport, determined through hit testing
  4. Return the result of running the retargeting algorithm with context object and HIT as input
ParameterTypeNullableOptionalDescription
xdouble
ydouble
Return type: Element, nullable
elementsFromPoint
Note

It could be defined in roughly the same way as elementFromPoint. Eventually, this needs to be part of CSSOM View Module specification [CSSOM-VIEW]. See also W3C bug 27829.

ParameterTypeNullableOptionalDescription
xdouble
ydouble
Return type: sequence<Element>
getSelection

Returns the current selection in the shadow tree.

When invoked, it must return the selection in the shadow tree.

No parameters.
Return type: Selection, nullable

The nodeType attribute of a ShadowRoot instance must return DOCUMENT_FRAGMENT_NODE. Accordingly, the nodeName attribute of a ShadowRoot instance must return "#document-fragment".

Invoking the cloneNode() method on a ShadowRoot instance must always throw a DATA_CLONE_ERR exception.

8.2 Extensions to Element Interface

partial interface Element {
    ShadowRoot attachShadow (ShadowRootInit shadowRootInitDict);
                attribute DOMString   slot;
    readonly    attribute ShadowRoot? shadowRoot;
};

8.2.1 Attributes

shadowRoot of type ShadowRoot, readonly , nullable

Represents the shadow root that context object hosts.

On getting, the attribute must return the shadow root that context object hosts if there is and it is open. Otherwise must return null.

slot of type DOMString,

Reflects the slot attribute. The slot attribute represents the slot name of a slot to where this element is assigned.

8.2.2 Methods

attachShadow
When invoked, these steps must be run:
  1. If the context object is one of the following elements, throws NotSupportedError exception.
    • button
    • details
    • input
    • marquee
    • meter
    • progress
    • select
    • textarea
    • keygen
    Note

    These are the elements whose rendering is defined through a binding property in HTML's Rendering section.

  2. If the context object already hosts the shadow tree, throws InvalidStateError exception.
  3. Create a new instance of the ShadowRoot object. The shadowRootInitDict argument allows for setting the encapsulation mode.
  4. Let the context object host the ShadowRoot object.
  5. Return ShadowRoot object.
ParameterTypeNullableOptionalDescription
shadowRootInitDictShadowRootInit
Return type: ShadowRoot

8.3 ShadowRootInit dictionary

dictionary ShadowRootInit {
    required ShadowRootMode mode;
};

8.3.1 Dictionary ShadowRootInit Members

mode of type ShadowRootMode, required
Specifies the encapsulation mode of ShadowRoot

8.4 ShadowRootMode enum

enum ShadowRootMode {
    "open",
    "closed"
};
Enumeration description
openSpecifies open encapsulation mode
closedSpecifies closed encapsulation mode

8.5 Extensions to NonDocumentTypeChildNode Interface

partial interface NonDocumentTypeChildNode {
    readonly    attribute HTMLSlotElement? assignedSlot;
};

8.5.1 Attributes

assignedSlot of type HTMLSlotElement, readonly , nullable

Represents the assigned slot of the context object.

On getting, the attribute must return the assigned slot of the context object, if there is, and the assigned slot participates in an open shadow tree. Otherwise must return null.

8.6 The slot element

The slot element is used to define a location of a slot.

If a slot element does not satisfy the condition of a slot, it must have the same rendering behavior as the HTMLUnknownElement.

Context
Where flow content is expected.
Content model
Transparent
Children
Anything as fallback content
Content attributes
Global attributes
name, the slot name
Represents the slot name.
DOM Interface
interface HTMLSlotElement : HTMLElement {
                attribute DOMString name;
    sequence<Node> getDistributedNodes ();
};

Attributes

name of type DOMString,
Must reflect the name attribute.

Methods

getDistributedNodes
When invoked, it must return result of running the following steps:
  1. If the context object is a slot:
    1. Return a sequence consisting of nodes in the distributed nodes of the context object.
  2. Otherwise:
    1. Return an empty sequence.
No parameters.
Return type: sequence<Node>

8.7 Extensions to EventInit Dictionary

partial dictionary EventInit {
             boolean scoped = false;
};

8.7.1 Dictionary EventInit Members

scoped of type boolean, , defaulting to false

Specifies the scoped flag of Event

8.8 Extensions to Event Interface

partial interface Event {
    readonly    attribute object  deepPath;
    readonly    attribute boolean scoped;
};

8.8.1 Attributes

deepPath of type object, readonly

Represents the event path.

On getting, the attribute must create and return a new JavaScript Array object, that must be equivalent to processing the following steps:

Input
EVENT, a context object
Output
PATH, an array of nodes
  1. If EVENT hasn't been dispatched, return a new empty array.
  2. Otherwise:
    1. Let PATH be the event path of EVENT.
    2. If EVENT is being dispatched:
      1. Let CURRENT-TARGET be the current target of EVENT.
    3. Otherwise:
      1. Let CURRENT-TARGET be the last node of PATH.
    4. Let PATH contain only a node which is an unclosed node of CURRENT-TARGET.
Issue 2

The API is not stable and may change. Use FrozenArray as the return type of the deepPath attribute in WebIDL. See Issue #101

scoped of type boolean, readonly

Returns the scoped flag.

9. Shadow DOM Example

Bob was asked to turn a simple list of links into a News Widget, which has links organized into two categories: breaking news and just news. The current document markup for the stories looks like this:

Example 2
<ul class="stories">
    <li><a href="//example.com/stories/1">A story</a></li>
    <li><a href="//example.com/stories/2">Another story</a></li>
    <li class="breaking" slot="breaking"><a href="//example.com/stories/3">Also a story</a></li>
    <li><a href="//example.com/stories/4">Yet another story</a></li>
    <li><a href="//example.com/stories/5">Awesome story</a></li>
    <li class="breaking" slot="breaking"><a href="//example.com/stories/6">Horrible story</a></li>
</ul>
Issue 3

It's weird that there are slot attributes in this markup because Bob has not decided to use Shadow DOM yet.

To organize the stories, Bob decides to use shadow DOM. Doing so will allow Bob to keep the document markup uncluttered, and harnessing the power of insertion point makes sorting stories by class name a very simple task. After getting another cup of Green Eye, he quickly mocks up the following shadow tree, to be hosted by the ul element:

Example 3
<div class="breaking">
    <ul>
        <slot name="breaking"></slot> <!-- slot for breaking news -->
    </ul>
</div>
<div class="other">
    <ul>
        <slot></slot> <!-- slot for the rest of the news -->
    </ul>
</div>

Bob then styles the newborn widget according to comps from the designer by adding this to the shadow tree mockup:

Example 4
<style>
    div.breaking {
        color: Red;
        font-size: 20px;
        border: 1px dashed Purple;
    }
    div.other {
        padding: 2px 0 0 0;
        border: 1px solid Cyan;
    }
</style>

While pondering if his company should start looking for a new designer, Bob converts the mockup to code:

Example 5
function createStoryGroup(className, slotName)
{
    var group = document.createElement('div');
    group.className = className;
    // Empty string in slot name attribute or absence thereof work the same, so no need for special handling.
    group.innerHTML = '<ul><slot name="' + slotName + '"></slot></ul>';
    return group;
}

function createStyle()
{
    var style = document.createElement('style');
    style.textContent = 'div.breaking { color: Red;font-size: 20px; border: 1px dashed Purple; }' +
        'div.other { padding: 2px 0 0 0; border: 1px solid Cyan; }';
    return style;
}

function makeShadowTree(storyList)
{
    var root = storyList.attachShadow({mode: 'open'});
    root.appendChild(createStyle());
    root.appendChild(createStoryGroup('breaking', 'breaking'));
    root.appendChild(createStoryGroup('other', ''));
}

document.addEventListener('DOMContentLoaded', function() {
    [].forEach.call(document.querySelectorAll('ul.stories'), makeShadowTree);
});

Well done, Bob! With the cup of coffee still half-full, the work is complete. Recognizing his awesomeness, Bob returns to teaching n00bs the ways of Splatoon.

A. Acknowledgements

David Hyatt developed XBL 1.0, and Ian Hickson co-wrote XBL 2.0. These documents provided tremendous insight into the problem of functional encapsulation and greatly influenced this specification.

Alex Russell and his considerable forethought triggered a new wave of enthusiasm around the subject of shadow DOM and how it can be applied practically on the Web.

Dominic Cooney, Hajime Morrita, and Roland Steiner worked tirelessly to scope the problem of functional encapsulation within the confines of the Web platform and provided a solid foundation for this document.

The editor would also like to thank Alex Komoroske, Anne van Kesteren, Brandon Payton, Brian Kardell, Darin Fisher, Eric Bidelman, Deepak Sherveghar, Edward O'Connor, Elisée Maurer, Elliott Sprehn, Erik Arvidsson, Glenn Adams, Jonas Sicking, Koji Ishii, Malte Ubl, Mike Taylor, Oliver Nightingale, Olli Pettay, Rafael Weinstein, Richard Bradshaw, Ruud Steltenpool, Sam Dutton, Sergey G. Grekhov, Shinya Kawanaka, Tab Atkins, Takashi Sakamoto, and Yoshinori Sano for their comments and contributions to this specification.

This list is too short. There's a lot of work left to do. Please contribute by reviewing and filing bugs—and don't forget to ask the editor to add your name into this section.

B. References

B.1 Normative references

[CSS3UI]
Tantek Çelik; Florian Rivoal. CSS Basic User Interface Module Level 3 (CSS3 UI). 7 July 2015. W3C Candidate Recommendation. URL: http://www.w3.org/TR/css-ui-3/
[CSSOM-VIEW]
Simon Pieters; Glenn Adams. CSSOM View Module. 17 December 2013. W3C Working Draft. URL: http://www.w3.org/TR/cssom-view/
[DOM]
Anne van Kesteren; Aryeh Gregor; Ms2ger; Alex Russell; Robin Berjon. W3C DOM4. 18 June 2015. W3C Last Call Working Draft. URL: http://www.w3.org/TR/dom/
[DOM-Level-3-Events]
Gary Kacmarcik; Travis Leithead. UI Events (formerly DOM Level 3 Events). 28 April 2015. W3C Working Draft. URL: http://www.w3.org/TR/uievents/
[DOM-PARSING]
Travis Leithead. DOM Parsing and Serialization. 17 June 2014. W3C Candidate Recommendation. URL: http://www.w3.org/TR/DOM-Parsing/
[EDITING]
Aryeh Gregor. HTML Editing APIs. URL: https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html
[HTML]
Ian Hickson. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[TOUCH-EVENTS]
Doug Schepers; Sangwhan Moon; Matt Brubeck; Arthur Barstow. Touch Events. 10 October 2013. W3C Recommendation. URL: http://www.w3.org/TR/touch-events/
[WAI-ARIA]
James Craig; Michael Cooper et al. Accessible Rich Internet Applications (WAI-ARIA) 1.0. 20 March 2014. W3C Recommendation. URL: http://www.w3.org/TR/wai-aria/

B.2 Informative references

[css-scoping-1]
Tab Atkins Jr.; Elika Etemad. CSS Scoping Module Level 1. 3 April 2014. W3C Working Draft. URL: http://www.w3.org/TR/css-scoping-1/