/
index.html
957 lines (803 loc) · 73.7 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
<!DOCTYPE html>
<html>
<head>
<title>Tabs - Shadow DOM Code Sample</title>
<style>
@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300,600);
</style>
<script src="tabs-control.js"></script>
</head>
<body>
<h1>Tabs</h1>
<article is="tabs">
<h2 id="about">About this Document</h2>
<section>
<p>All diagrams, examples, notes, are non-normative, as well as sections explicitly marked as non-normative. Everything else in this specification is normative.</p>
<p>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 <a href="http://dev.w3.org/2006/xbl2/#refsRFC2119">RFC2119</a>. For readability, these words do not appear in all uppercase letters in this specification.</p>
<p>To help with layering and to avoid circular dependencies between various parts of specification, this document consists of three consecutive narratives:
<ol>
<li>setting up the stage for the specification,</li>
<li>explaining of the conceptual model and algorithms behind it, and</li>
<li>expressing this model with DOM interfaces and HTML elements.</li>
</ol>
<p>In a sense, these parts can be viewed as <em>math</em>, which sets up the reasoning environment, <em>physics</em>, which is the theoretical reasoning about the concept, and <em>mechanics</em>, which is the is the practical application of this reasoning.</p>
<p>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 <a href="http://en.wikipedia.org/wiki/Algorithm">algorithm</a>. The algorithms are defined in terms of processing equivalence. The <dfn id="dfn-processing-equivalence">processing equivalence</dfn> 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.</p>
</section>
<h2 id="dependencies">Dependencies</h2>
<section>
<p>This document relies on the following specifications:</p>
<ul>
<li><a href="http://www.w3.org/TR/CSS2/">CSS Level 2 Revision 1</a></li>
<li><a href="http://dev.w3.org/csswg/cssom/">CSSOM</a></li>
<li><a href="http://www.w3.org/TR/DOM-Level-3-Events/">DOM Level 3 Events</a></li>
<li><a href="http://www.w3.org/TR/domcore/">DOM4 (DOM Core)</a></li>
<li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/">HTML</a></li>
<li><a href="http://html5.org/specs/dom-parsing.html">DOM Parsing and Serialization</a></li>
<li><a href="http://www.w3.org/TR/selectors/">Selectors Level 3</a></li>
<li><a href="http://dev.w3.org/2006/webapi/selectors-api/">Selectors API Level 1</a></li>
</ul>
</section>
<h2 id="terminology">Terminology</h2>
<section>
<p>The following terms are used throughout the specification:
<dl>
<dt>DOM</dt>
<dd>The <a href="http://www.w3.org/TR/domcore/">document object model</a></dd>
<dt>document</dt>
<dd>The Document Object Model's underlying document</dd>
<dt>node</dt>
<dd>Any DOM object that <a href="http://www.w3.org/TR/domcore/#concept-tree-participate">participates in a tree</a></dd>
<dt>element</dt>
<dd>A DOM object that implements the <a href="http://www.w3.org/TR/domcore/#interface-element">Element</a> interface</dd>
<dt>DOM tree</dt>
<dd>Any <a href="http://www.w3.org/TR/domcore/#trees">tree</a>, composed of DOM objects</a>
<dt>DOM structure</dt>
<dd>A DOM tree or fragment of a DOM tree</a>
</dl>
</section>
<h2 id="introduction">Introduction</h2>
<section>
<p>Web application developers often encounter the need to provide <dfn id="dfn-encapsulation">encapsulation</dfn> of a DOM structure. Despite being part of one document tree, there are typically many functional fragments of DOM (or <dfn id="dfn-dom-subtree">DOM subtrees</dfn>), as well as assumptions about these fragments operating independently. This type of encapsulation is called <dfn id="dfn-functional-encapsulation">functional encapsulation</dfn>, as opposed to <dfn id="dfn-trust-encapsulation">trust encapsulation</dfn>, which deals with limiting information flow based on trust and ensuring security of data and state within an application.</p>
<p><a href="#dfn-functional-encapsulation">Functional encapsulation</a> is primarily concerned with establishing functional boundaries in a document tree. A functional boundary (or just <dfn id="dfn-boundary">boundary</dfn> hereon) is a delineation of functional concerns between two loosely coupled units of functionality.</p>
<h3 id="functional-encapsulation-example">Functional Encapsulation Example</h3>
<p>A Web application user interface is commonly composed of several user interface elements (or <dfn id="dfn-widget">widgets</dfn>), each a DOM subtree. In cases where a widget is tasked with hosting other widgets, the need arises for the widget to understand where its DOM subtree ends and another widget's DOM subtree begins.</p>
<p>This need for observing the functional <a href="#dfn-boundary">boundaries</a> in a document tree is even larger when a <a href="#dfn-widget">widget</a> is operated on—added, moved, or removed in the document tree—by an outside actor, such as the Web application that consumes these widgets. Unless the widget consumer knows exactly how a widget's DOM structure is designed, it is impossible for the consumer to reasonably operate on the widget. A typical workaround has been providing alternative means of operation by the widget developer, which, in striving for API consistency quickly extrapolates into a complete set of widget-specific, DOM-like APIs.</p>
</section>
<h2 id="shadow-dom-subtrees">Shadow DOM Subtrees</h2>
<section>
<p>To solve this problem at its core, a new abstraction is introduced. The <dfn id="dfn-shadow-dom">shadow DOM</dfn> allows multiple DOM subtrees (in addition to the document tree) to be composed into one larger tree when rendered. The existence of multiple DOM subtrees is enabled by letting any element in the document tree to host one or more additional DOM subtrees. These <dfn id="dfn-shadow-dom-subtree">shadow DOM subtrees</dfn> are governed by a set of rules that establish encapsulation <a href="#dfn-boundary">boundaries</a> while retaining the standard DOM composability semantics.</p>
<p>The encapsulation <a href="#dfn-boundary">boundaries</a> between shadow DOM subtrees are called <dfn id="dfn-shadow-boundary">shadow boundaries</dfn>. The elements that host shadow DOM subtrees are called <dfn id="dfn-shadow-host">shadow hosts</dfn>, and the root nodes of the shadow DOM subtrees are called <dfn id="dfn-shadow-root">shadow roots</dfn>.</p>
<p>When rendered, the shadow DOM subtree takes place of the host element's content.</p>
<p>To enable composition of host element's children and the shadow DOM subtree, a notion of insertion points is added to the abstraction. An <dfn id="dfn-insertion-point">insertion point</dfn> is a defined location in the shadow DOM subtree, to which the host element's children are transposed when rendering.</p>
<p>Thus, the encapsulation of a shadow DOM subtree can be viewed as a two-fold problem:
<ol>
<li>the <dfn id="dfn-upper-boundary-encapsulation">upper-boundary encapsulation</dfn>, or governing the boundary between the shadow root and the shadow host; and</li>
<li>the <dfn id="dfn-lower-boundary-encapsulation">lower-boundary encapsulation</dfn>, or governing the boundary between the insertion points and the shadow host's children.</li>
</ol>
<h3 id="upper-boundary-encapsulation">Upper-boundary Encapsulation</h3>
<p>To maintain the upper-boundary encapsulation, the following <dfn id="dfn-scoping-constraints">scoping constraints</dfn> must apply to all nodes in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>:</p>
<ul>
<li>The <a href="http://www.w3.org/TR/domcore/#dom-node-ownerdocument"><code>ownerDocument</code></a> property refers to the document of the <a href="#dfn-shadow-host">shadow host</a></li>
<li>The nodes and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#dom-document-nameditem-filter">named elements</a> <strong>are not</strong> accessible using <a href="#dfn-shadow-host">shadow host</a>'s document <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#dom-tree-accessors">DOM tree accessors</a></li>
<li>The nodes with a unique <a href="http://www.w3.org/TR/domcore/#concept-id">id</a> and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#dom-document-nameditem-filter">named elements</a> <strong>are not</strong> addressable from any attributes of elements in <a href="#dfn-shadow-host">shadow host</a>'s document</li>
<li>The stylesheets, represented by the nodes <strong>are not</strong> accessible using <a href="#dfn-shadow-host">shadow host</a> document's <a href="http://dev.w3.org/csswg/cssom/#extensions-to-the-document-interface">CSSOM extensions</a></li>
<li>The nodes <strong>are</strong> accessible using <a href="#dfn-shadow-root">shadow root</a>'s DOM tree accessor methods</li>
<li>The nodes with a unique <a href="http://www.w3.org/TR/domcore/#concept-id">id</a> and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#dom-document-nameditem-filter">named elements</a> <strong>are</strong> addressable from any attributes of elements in the same <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a></li>
<li>The <a href="http://www.w3.org/TR/selectors/">selectors</a> <strong>must not</strong> cross the <a href="#dfn-shadow-boundary">shadow boundary</a></li>
</ul>
<p>For convenience, the <a href="#dfn-shadow-root">shadow root</a> provides its own set of DOM tree accessor methods. No nodes other than <a href="#dfn-shadow-root">shadow root</a> descendants are accessible with these methods.</p>
<p>The <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/dom-core.html#dom-node-parentnode"><code>parentNode</code></a> and <a href="http://dvcs.w3.org/hg/domcore/raw-file/tip/dom-core.html#dom-node-parentelement"><code>parentElement</code></a> attributes of the <a href="#dfn-shadow-root">shadow root</a> object must always return <code>null</code>.</p>
<h3 id="lower-boundary-encapsulation">Lower-boundary Encapsulation</h3>
<p>To maintain the lower-boundary encapsulation, the distribution of child nodes of the <a href="#dfn-shadow-host">shadow host</a> among the <a href="#dfn-insertion-point">insertion points</a> in the associated <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a> must have the following traits:</p>
<ul>
<li>The distribution does not affect the state of the document DOM tree or shadow DOM subtrees</li>
<li>Each insertion point participates in distribution by providing a matching criteria for the child nodes. The <dfn id="dfn-matching-criteria">matching criteria</dfn> determines whether a given node could be distributed to a given insertion point</li>
<li>The distribution is a result of executing a stable algorithm</li>
<li>The distribution itself does not change the variables affecting the distribution</li>
<li>The distribution reoccurs whenever any variable affecting it is changed</li>
</ul>
<p>An <a href="#dfn-insertion-point">insertion point</a> may be <strong>active</strong> or <strong>inactive</strong>. An <dfn id="dfn-active-insertion-point">active</dfn> insertion point participates in the distribution process, whereas the <dfn id="dfn-inactive-insertion-point">inactive</dfn> insertion does not. If not specifically set to be inactive, the insertion point must be considered <strong>active</strong>.</p>
The <dfn id="dfn-distribution-algorithm">distribution algorithm</dfn> must produce an outcome that is <a href="#dfn-processing-equivalence">equivalent</a> of the outcome of processing these steps:</p>
<div class="algorithm">
<dl>
<dt>Input</dt>
<dd><var>TREE</var>, a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a></dd>
<dd><var>POOL</var>, a list of DOM nodes</dd>
<dt>Output</dt>
<dd>The nodes in <var>POOL</var> are distributed among <a href="#dfn-insertion-point">insertion points</a> in <var>TREE</var>.</dd>
</dl>
<ol>
<li><dfn id="algo-distribution-repeat-outer">Repeat</dfn> for each <a href="#dfn-active-insertion-point">active</a> <a href="#dfn-insertion-point">insertion point</a> in <var>TREE</var>, in <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#tree-order">tree order</a>:
<ol>
<li>Let <var>POINT</var> be the current insertion point</li>
<li><dfn id="algo-distribution-repeat">Repeat</dfn> for each node in <var>POOL</var>:
<ol>
<li>Let <var>NODE</var> be the current node</li>
<li>If the <var>NODE</var> matches <var>POINT</var>'s <a href="#dfn-matching-criteria">matching criteria</a>:</li>
<ol>
<li>Distribute the <var>NODE</var> to <var>POINT</var></li>
<li>Remove <var>NODE</var> from the <var>POOL</var></li>
</ol></li>
<li>Otherwise, continue to <a href="#algo-distribution-repeat">repeat</a></li>
</ol></li>
<li>Continue to <a href="#algo-distribution-repeat-outer">repeat</a></li>
</ol></li>
</ol>
</div>
<h3 id="matching-insertion-points">Matching Insertion Points</h3>
<p>The <a href="#dfn-matching-criteria">matching criteria</a> for <a href="#dfn-insertion-point">insertion point</a> is defined as a set of selector fragments. Each <dfn id="dfn-selector-fragment">selector fragment</dfn> is indeed a fragment in the <a href="http://www.w3.org/TR/css3-selectors">selector</a> <code>(shadow-host)>(fragment)</code>, where <code>(shadow-host)</code> is a selector that uniquely identifies the <a href="#dfn-shadow-host">shadow host</a>, and <code>(fragment)</code> is the <a href="#dfn-selector-fragment">selector fragment</a>.</p>
<p>A <dfn id="dfn-valid-selector-fragment">valid selector fragment</dfn> may contain:</p>
<ul>
<li>A <a href="http://www.w3.org/TR/css3-selectors/#type-selectors">type selector</a> or a <a href="http://www.w3.org/TR/css3-selectors/#universal-selector">universal selector</a></li>
<li><a href="http://www.w3.org/TR/css3-selectors/#class-html">class selector(s)</a></li>
<li>An <a href="http://www.w3.org/TR/css3-selectors/#id-selectors">ID selector</a></li>
<li><a href="http://www.w3.org/TR/css3-selectors/#attribute-selectors">attribute selector(s)</a></li>
<li>the following <a href="http://www.w3.org/TR/css3-selectors/#pseudo-classes">pseudo-class selector(s)</a>:
<ul>
<li><code>:link</code></li>
<li><code>:visited</code></li>
<li><code>:target</code></li>
<li><code>:enabled</code></li>
<li><code>:disabled</code></li>
<li><code>:checked</code></li>
<li><code>:indeterminate</code></li>
<li><code>:nth-child()</code></li>
<li><code>:nth-last-child()</code></li>
<li><code>:nth-of-type()</code></li>
<li><code>:nth-of-last-type()</code></li>
<li><code>:first-child</code></li>
<li><code>:last-child</code></li>
<li><code>:first-of-type</code></li>
<li><code>:last-of-type</code></li>
<li><code>:only-of-type</code></li>
</ul>
</li>
</ul>
<p>If any other types of selectors are present the <a href="#dfn-selector-fragment">selector fragment</a>, the fragment must be considered invalid.</p>
<p>A conforming UAs must consider a node as <dfn id="#dfn-content-matching">matching</dfn> a set of <a href="#dfn-selector-fragment">selector fragments</a> in the context of a given <a href="#dfn-shadow-host">shadow host</a>, if it:
<ol>
<li>is a child node of the shadow host; and</li>
<li>all <a href="#dfn-selector-fragment">selector fragments</a> in the set are <a href="#dfn-valid-selector-fragment">valid</a>; and</li>
<li>child node matches at least one selector fragment in the set or the set is empty.</li>
</ol>
<h3 id="multiple-shadow-subtrees">Hosting Multiple Shadow Subtrees</h3>
<p>A <a href="#dfn-shadow-host">shadow host</a> may host more than one <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>. In such cases, the subtrees are stacked in the order they were added the the host, starting with the subtree added most recently. This set of trees is called a <dfn id="dfn-tree-stack">tree stack</dfn>. The more recently added subtree is called the <dfn id="dfn-younger-tree">younger tree</dfn>, and the less recently added subtree is called the <dfn id="dfn-older-tree">older tree</dfn>. The most recently added subtree is called the <dfn id="dfn-youngest-tree">youngest tree</dfn>.</p>
<p>To facilitate composing multiple shadow subtrees of the same host, a special kind of <a href="#dfn-insertion-point">insertion point</a> is defined. The <dfn id="dfn-shadow-insertion-point">shadow insertion point</dfn> designates a place in the <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, where an <a href="#dfn-older-tree">older tree</a> is inserted.</p>
<p>Just like other <a href="#dfn-insertion-point">insertion points</a>, the <a href="#dfn-shadow-insertion-point">shadow insertion points</a> can be <a href="#dfn-active-insertion-point">active</a> or <a href="#dfn-inactive-insertion-point">inactive</a>.</p>
<p>The composition is performed with the <dfn id="dfn-tree-composition">tree composition algorithm</dfn>, which must be <a href="#dfn-processing-equivalence">equivalent</a> to processing the following steps:
<div class="algorithm">
<dl>
<dt>Input</dt>
<dd><var>HOST</var>, a <a href="#dfn-shadow-host">shadow host</a></dd>
<dt>Output</dt>
<dd>All <a href="#dfn-insertion-point">insertion points</a> and <a href="#dfn-shadow-insertion-point">shadow insertion points</a> are populated.</dd>
</dl>
<ol>
<li>Let <var>TREE</var> be the <a href="#dfn-youngest-tree">youngest tree</a> in the <var>HOST</var>'s <a href="#dfn-tree-stack">tree stack</a>
<li>Let <var>POOL</var> be the list of nodes</li>
<li>Populate <var>POOL</var> with child nodes of the <var>HOST</var></li>
<li><dfn id="algo-composition-repeat">Repeat</dfn> while <var>TREE</var> exists:</li>
<ol>
<li>Let <var>POINT</var> be the first encountered <a href="#dfn-active-insertion-point">active</a> <a href="#dfn-shadow-insertion-point">shadow insertion point</a> in <var>TREE</var>, in <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#tree-order">tree order</a>
<li>Run the <a href="#dfn-distribution-algorithm">distribution algorithm</a>, supplying <var>POOL</var> and <var>TREE</var> as input</li>
<li>If <var>POINT</var> exists:
<ol>
<li>Find the next older tree, relative to <var>TREE</var> in the <var>HOST</var>'s <a href="#dfn-tree-stack">tree stack</a>
<ol>
<li>If there is no older tree:
<ol>
<li>Distribute remaining nodes in <var>POOL</var>, if any, to <var>POINT</var></li>
<li><strong>stop</strong>.</li>
</ol></li>
<li>Otherwise:
<ol>
<li>Set <var>TREE</var> to be this older tree</li>
<li><dfn id="dfn-assign-older-tree">Assign</dfn> <var>TREE</var> to the <var>POINT</var></li>
<li>Continue to <a href="#algo-composition-repeat">repeat</a></li>
</ol></li>
</ol></li>
</ol></li>
<li>Otherwise, <strong>stop</strong>.
</ol></li>
</ol>
</div>
<p>When an <a href="#dfn-insertion-point">insertion point</a> or a <a href="#dfn-shadow-insertion-point">shadow insertion point</a> has nothing <a href="#dfn-assign-older-tree">assigned</a> or <a href="#dfn-distribution-algorithm">distributed</a> to them, the fallback content must be used instead when rendering. The <dfn id="dfn-fallback-content">fallback content</dfn> is all descendants of the DOM element that represents the insertion point. The <a href="#dfn-insertion-point">insertion points</a> or <a href="#dfn-shadow-insertion-point">shadow insertion points</a> in fallback content must be considered <a href="#dfn-inactive-insertion-point">inactive</a>.</p>
<h3 id="nested-shadow-subtrees">Nested Shadow Subtrees</h3>
<p>Any element in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a> can be a <a href="#dfn-shadow-host">shadow host</a>, thus producing nested shadow DOM subtrees. A shadow DOM subtree is <dfn id="dfn-nested-subtree">nested</dfn> when its <a href="#dfn-shadow-host">shadow host</a> is itself a part of a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>.</p>
<h3 id="rendering-shadow-subtrees">Rendering Shadow DOM Subtrees</h3>
<p><dfn id="dfn-rendering">Rendering</dfn> of <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>, or presenting them visually, is defined as a specialization of rendering <strong>any DOM subtree</strong>, and must happen as these steps:</p>
<div class="algorithm">
<dl>
<dt>Input</dt>
<dd><var>HOST</var>, a <a href="#dfn-shadow-host">shadow host</a></dd>
<dt>Output</dt>
<dd>Rendering of the <var>HOST</var>, including its <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a></dd>
</dl>
<ol>
<li>Run <a href="#dfn-tree-composition-algorithm">tree composition algorithm</a> for the given <a href="#dfn-shadow-host">shadow host</a></li>
<li>As content of the <a href="#dfn-shadow-host">shadow host</a>, render the <a href="#dfn-youngest-tree">youngest tree</a> as a <strong>any DOM subtree</strong>, with the following <dfn id="dfn-shadow-rendering">shadow rendering</dfn> exceptions:
<ul>
<li>Each element that is a <a href="#dfn-shadow-host">shadow host</a> must be <a href="#dfn-rendering">rendered</dfn> accordingly</li>
<li>In place of each <a href="#dfn-insertion-point">insertion point</a>, process the following <dfn id="dfn-insertion-point-rendering">insertion point rendering</dfn> steps:
<ol>
<li>If there are child nodes <a href="#dfn-distribution-algorithm">distributed</a> to this insertion point, for each child node and in the order they were distributed:
<ol>
<li>Let <var>CHILD</var> be the child node being rendered</li>
<li>If <var>CHILD</var> is itself an <a href="#dfn-insertion-point">insertion point</a>, and the tree being rendered is <a href="#dfn-nested-subtree">nested</a>, render them using <a href="#dfn-insertion-point-rendering">insertion point rendering</a> steps</li>
<li>Otherwise, render <var>CHILD</var> as <strong>any DOM subtree</strong>
</ol></li>
<li>Otherwise, render <a href="#dfn-fallback-content">fallback content</a> as <strong>any DOM subtree</strong></li>
</ol></li>
<li>In place of each <a href="#dfn-shadow-insertion-point">shadow insertion point</a>:
<ol>
<li>If there is an <a href="#dfn-older-tree">older tree</a>, <a href="#dfn-assign-older-tree">assigned</a> to this shadow insertion point, render it as <strong>any DOM subtree</strong>, but with the same <a href="#dfn-shadow-rendering">shadow rendering</a> exceptions.</li>
<li>Otherwise, render <a href="#dfn-fallback-content">fallback content</a> as <strong>any DOM subtree</strong></li>
</ol></li>
</ul></li>
</ol>
</div>
<p>This process of <a href="#dfn-rendering">rendering</a> produces a structure that is a composition of several DOM subtrees, including the document tree. The term "<dfn id="dfn-as-rendered">as rendered</dfn>" is used to refer to this structure.</p>
</section>
<h2 id="events">Events</h2>
<section>
<p>In <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>, the <a href="http://www.w3.org/TR/domcore/#events">DOM Events</a> are allowed to cross the <a href="#dfn-shadow-boundary">shadow boundaries</a> under some conditions.</p>
<p>When an event is fired in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, it either <em>escapes</em> out of the shadow tree during the capture, target, or bubble phases or it <em>is stopped</em> at the <a href="#dfn-shadow-boundary">shadow boundary</a>.</p>
<p>In terms of <a href="http://www.w3.org/TR/domcore/#dispatching-events">DOM event dispatch</a>, this manifests in populating the list of ancestors of the target node with <dfn id="dfn-adjusted-parent">adjusted parent</dfn> nodes, or nodes that appear as parents <a href="#dfn-as-rendered">as rendered</a>. The <dfn id="dfn-parent-calculation-algorithm">parent calculation algorithm</dfn> is used to determine the <a href="#dfn-adjusted-parent">adjusted parent</a> of any given node and create the list of ancestors for event dispatch. This algorithm must be <a href="#dfn-processing-equivalence">equivalent</a> to processing the following steps:</p>
<div class="algorithm">
<dl>
<dt>Input</dt>
<dd><var>NODE</var>, a DOM node</dd>
<dt>Output</dt>
<dd><var>PARENT</var>, a DOM node's <a href="#dfn-adjusted-parent">adjusted parent</a></dd>
</dl>
<ol>
<li>If <var>NODE</var> is currently distributed to an <a href="#dfn-insertion-point">insertion point</a> in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>
<ol>
<li>Let the <var>PARENT</var> be the <a href="#dfn-insertion-point">insertion point</a> to which the <var>NODE</var> is distributed to</li>
</ol></li>
<li>If <var>NODE</var> is a <a href="#dfn-shadow-root">shadow root</a>:
<ol>
<li>If <var>NODE</var> is currently <a href="#dfn-assign-older-tree">assigned</a> to a <a href="#dfn-shadow-insertion-point">shadow insertion point</a>:
<ol>
<li>Let the <var>PARENT</var> be the <a href="#dfn-shadow-insertion-point">shadow insertion point</a> to which <var>NODE</var> is <a href="#dfn-assign-older-tree">assigned</a> to</li>
</ol></li>
<li>Otherwise, let the <var>PARENT</var> be the <a href="#dfn-shadow-host">shadow host</a> of the <var>NODE</var>
</ol></li>
<li>Otherwise, let <var>PARENT</var> be the node's parent node.</li>
</ol>
</div>
<h3 id="event-retargeting">Event Retargeting</h3>
<p>In the cases where event escapes the shadow tree, the event's information about the target of the event is adjusted in order to maintain <a href="#dfn-upper-boundary-encapsulation">upper boundary encapsulation</a>. Event <dfn id="dfn-retargeting">retargeting</dfn> is a process of computing relative targets for each ancestor of the node at which the event is dispatched. A <dfn id="dfn-relative-target">relative target</dfn> is a DOM node that most accurately represents the target of a dispatched event at a given ancestor while maintaining the <a href="#dfn-upper-boundary-encapsulation">upper boundary encapsulation</a>.
<p>The <dfn id="dfn-retargeting-algorithm">retargeting algorithm</dfn> is used to determine relative targets, and it must be <a href="#dfn-processing-equivalence">equivalent</a> to processing the following steps:</p>
<div class="algorithm">
<dl>
<dt>Input</dt>
<dd><var>NODE</var>, a DOM node</dd>
<dt>Output</dt>
<dd><var>TARGETS</var>, a list of tuples, each containing <var>NODE</var>'s ancestor and its relative target</dd>
</dl>
<ol>
<ol>
<li>Let <var>BOUNDARY</var> be a flag, initialized to <strong>false</strong></li>
<li>Let <var>TARGET</var> be <var>NODE</var>
<li>Let <var>ANCESTOR</var> be <var>NODE</var></li>
<li><dfn id="algo-reatargeting-repeat">Repeat</dfn> while <var>ANCESTOR</var> exists:
<ol>
<li>If <var>ANCESTOR</var> <strong>is</strong> a <a href="#dfn-shadow-root">shadow root</a>, set <var>BOUNDARY</var> to <strong>true</strong></li>
<li>Otherwise:
<ol>
<li>If <var>BOUNDARY</var> is set to <strong>true</strong>
<ol>
<li>Set <var>TARGET</var> to <var>ANCESTOR</var></li>
<li>Set <var>BOUNDARY</var> to <strong>false</strong> state</li>
</ol></li>
<li>Add (<var>TARGET</var>, <var>ANCESTOR</var>) tuple to <var>TARGETS</var></li>
</ol></li>
<li>Set <var>ANCESTOR</var> to be the result of <a href="#dfn-parent-calculation-algorithm">parent calculation algorithm</a>, given <var>ANCESTOR</var> as input</li>
</ol></li>
</ol>
</div>
<p>The retargeting process must occur prior to dispatch of an event.</p>
<h3 id="retargeting-related-target">Retargeting <code>relatedTarget</code></h3>
<p>Some events have a <a href="http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-relatedTarget"><code>relatedTarget</code></a> property, which holds a node that's not the event's target, but is related to the event.</p>
<p>For instance, a <code>mouseover</code> event's <a href="http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-relatedTarget"><code>relatedTarget</code></a> may hold the node from which the mouse has moved to event's <code>target</code>. In the case where <code>relatedTarget</code> is in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, the conforming UAs must not leak its actual value outside of this subtree. In cases where both <code>relatedTarget</code> and <code>target</code> are part of the same <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, the conforming UAs must <em>stop</em> events at the <a href="#dfn-shadow-boundary">shadow boundary</a> to avoid the appearance of spurious <code>mouseover</code> and <code>mouseout</code> events firing from the same node.</p>
<p>Thus, if an event has a <code>relatedTarget</code>, its value and extent of event dispatch must be adjusted. In general:</p>
<ol>
<li>If <code>relatedTarget</code> and <code>target</code> are enclosed by a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, the event dispatch must be stopped at the <a href="#dfn-shadow-boundary">shadow boundary</a> of this subtree. This boundary is called <dfn id="dfn-lowest-common-boundary">lowest common boundary</dfn></li>
<li>If <code>relatedTarget</code> is separated from <code>target</code> by one or more <a href="#dfn-shadow-boundary">shadow boundaries</a>, it must be retargeted to the boundary that's closest to <code>target</code>. This boundary is called <dfn id="dfn-first-divergent-boundary">first divergent boundary</dfn>.</li>
</ol>
<p>The <dfn id="dfn-related-target-algorithm">related target resolution</dfn> algorithm is used to determine dispatch behavior of events with a <a href="http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-relatedTarget"><code>relatedTarget</code></a> property, which must be <a href="#dfn-processing-equivalence">equivalent</a> to processing the following steps:</p>
<div class="algorithm">
<dl>
<dt>Input</dt>
<dd><var>TARGET</var>, the target DOM node of the event</dd>
<dd><var>RELATED</var>, the related target DOM node of the event</dd>
<dt>Output</dt>
<dd><var>LIMIT</var>, the ancestor DOM node of <var>TARGET</var>, at which the event dispatch must be stopped (not including <var>LIMIT</var> itself)</dd>
<dd><var>ADJUSTED</var>, the <dfn id="dfn-adjusted-related-target">adjusted related target</dfn> DOM node</dd>
</dl>
<ol>
<li>Let <var>COMMON</var> be <strong>undefined</strong></li>
<li>Let <var>ANCESTOR</var> be the <a href="http://en.wikipedia.org/wiki/Lowest_common_ancestor">lowest common ancestor</a> of <var>TARGET</var> and <var>RELATED</var>, computed using <a href="#dfn-parent-calculation-algorithm">parent calculation algorithm</a> when determining ancestry</li>
<li>If <var>ANCESTOR</var> exists:
<ol>
<li>If <var>ANCESTOR</var> is <var>RELATED</var> and is a <a href="#dfn-shadow-host">shadow host</a>:
<ol>
<li>Set <var>LIMIT</var> to <var>ANCESTOR</var></li>
<li>Set <var>ADJUSTED</var> to <var>RELATED</var></li>
<li>Stop.</li>
</ol></li>
<li>Otherwise:
<ol>
<li>Let <var>ROOT</var> be the nearest ancestor <a href="#dfn-shadow-root">shadow root</a> of <var>ANCESTOR</var></li>
<li>If <var>ROOT</var> exists, set <var>COMMON</var> and <var>LIMIT</var> to <var>ROOT</var>'s <a href="#dfn-shadow-host">shadow host</a></li>
</ol></li>
</ol></li>
<li>If <var>COMMON</var> is still <strong>undefined</strong>, set <var>COMMON</var> to the farthest ancestor of <var>RELATED</var>, computed using <a href="#dfn-parent-calculation-algorithm">parent calculation algorithm</a> when determining ancestry</li>
<li>Let <var>HOST</var> be the farthest <a href="#dfn-shadow-host">shadow host</a> ancestor of <var>RELATED</var> that is also a descendant of <var>COMMON</var>, computed using <a href="#dfn-parent-calculation-algorithm">parent calculation algorithm</a> when determining ancestry</li>
<li>If <var>HOST</var> exists, set <var>ADJUSTED</var> to <var>HOST</var></li>
<li>Otherwise, set <var>ADJUSTED</var> to <var>RELATED</var></li>
</ol>
</div>
<h3 id="retargeting-focus-events">Retargeting Focus Events</h3>
<p>The <code>focus</code>, <code>DOMFocusIn</code>, <code>blur</code>, and <code>DOMFocusOut</code> events must be treated in the same way as events with a <code>relatedTarget</code>, where the corresponding node that is losing focus as a result of <code>target</code> gaining focus or the node that is gaining focus, and thus causing the blurring of <code>target</code> acts as the related target.</p>
<h3 id="events-that-are-always-stopped">Events that are Always Stopped</h3>
<p>Mutation events and <code>selectstart</code> event are always stopped at the nearest <a href="#dfn-shadow-boundary">shadow boundary</a>.</p>
<h3 id="event-dispatch">Event Dispatch</h3>
<p>At the time of event dispatch:</p>
<ul>
<li>The <a href="http://www.w3.org/TR/domcore/#event"><code>Event</code></a> <a href="http://www.w3.org/TR/domcore/#dom-event-target"><code>target</code></a> and <a href="http://www.w3.org/TR/domcore/#dom-event-currenttarget"><code>currentTarget</code></a> attributes <strong>must</strong> return the <a href="#dfn-relative-target">relative target</a> for the node on which event listeners are <a href="http://www.w3.org/TR/domcore/#concept-event-listener-invoke">invoked</a></li>
<li>The <a href="http://www.w3.org/TR/DOM-Level-3-Events/#events-UIEvent"><code>UIEvent</code></a> <a href="http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-relatedTarget"><code>relatedTarget</code></a> attribute <strong>must</strong> return the <a href="#dfn-adjusted-related-target">adjusted related target</a></li>
<li>When <em>capturing</em>, which entails processing step 3 of the <a href="http://www.w3.org/TR/domcore/#dispatching-events">event dispatch algorithm</a>, the <a href="http://www.w3.org/TR/domcore/#event"><code>Event</code></a> <a href="http://www.w3.org/TR/domcore/#dom-event-eventphase">eventPhase</a> attribute <strong>must</strong> return <a href="http://www.w3.org/TR/domcore/#dom-event-at_target">AT_TARGET</a> <strong>if</strong> the <a href="#dfn-relative-target">relative target</a> is same as the node on which event listeners are <a href="http://www.w3.org/TR/domcore/#concept-event-listener-invoke">invoked</a></li>
<li>When <em>bubbling</em>, which entails processing step 6 of the <a href="http://www.w3.org/TR/domcore/#dispatching-events">event dispatch algorithm</a>, the event listeners <strong>must not</strong> be <a href="http://www.w3.org/TR/domcore/#concept-event-listener-invoke">invoked</a> on a node <strong>if</strong> it is the same as its <a href="#dfn-relative-target">relative target</a></li>
</ul>
<p>Upon completion of the event dispatch, the <a href="http://www.w3.org/TR/domcore/#event"><code>Event</code></a> object's <a href="http://www.w3.org/TR/domcore/#dom-event-target"><code>target</code></a> and <a href="http://www.w3.org/TR/domcore/#dom-event-currenttarget"><code>currentTarget</code></a> <strong>must</strong> be to the highest ancestor's <a href="#dfn-relative-target">relative target</a>. Since it is possible for a script to hold on to the <code>Event</code> object past the scope of event dispatch, this step is necessary to avoid revealing the nodes in <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>.</p>
<h3 id="event-retargeting-example">Event Retargeting Example</h3>
<p>Suppose we have a user interface for a media controller, represented by this DOM tree, composed of both document and the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>. 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 <code>shadow-boundary</code> element to demarcate the <a href="#dfn-shadow-boundary">shadow boundaries</a>:</p>
<pre><code>
<div id="player">
<span class=shadow-boundary><shadow-boundary></span>
<div class="controls">
<button class="play-button">
<input type="range" class="timeline">
<span class=shadow-boundary><shadow-boundary></span>
<div class="slider-thumb"></div>
<span class=shadow-boundary></shadow-boundary></span>
</input>
<div class="volume-slider-container">
<input type="range" class="volume-slider">
<span class=shadow-boundary><shadow-boundary></span>
<div class="slider-thumb"></div>
<span class=shadow-boundary></shadow-boundary></span>
</input>
</div>
</div>
<span class=shadow-boundary></shadow-boundary></span>
</div>
</code></pre>
<p>Let's have a user position their pointing device over the volume slider's thumb (<code>#player .volume-slider .slider-thumb</code>), thus triggering a <code>mouseover</code> event on that node. For this event, let's pretend it has no associated <code>relatedTarget</code>.</p>
<p>Just before the event is dispatched, we perform <a href="#dfn-retargeting">retargeting</a>:</p>
<ol>
<li>We set the <a href="#dfn-relative-target">relative target</a> of the thumb node to itself.</li>
<li>Walking up, we find a <a href="#dfn-shadow-boundary">shadow boundary</a> and skip it.</li>
<li>Next up is an input (<code>#player .volume-slider</code>), and we set its relative target to itself, since the previous ancestor was a shadow boundary.</li>
<li>We then walk up to the containing div (<code>#player .volume-slider-container</code>), and use previous ancestor's target -- the input element.</li>
<li>Walking up one more, we reach the controls panel (<code>#player .controls</code>), and again use input element as relative target per <a href="#dfn-retargeting-algorithm">retargeting algorithm</a>.</li>
<li>Next, we reach another <a href="#dfn-shadow-boundary">shadow boundary</a> and skip it.</li>
<li>Finally we walk up to the player element (<code>#player</code>) and set its relative target to itself.</li>
</ol>
<pre class="example html"><code>
<span class=event-ancestor><div id="player"> <em>7</em></span>
<span class="shadow-boundary event-ancestor"><shadow-boundary> <em>6</em></span>
<span class=event-ancestor><div class="controls"> <em>5</em></span>
<button class="play-button">
<input type="range" class="timeline">
<span class=shadow-boundary><shadow-boundary></span>
<div class="slider-thumb"></div>
<span class=shadow-boundary></shadow-boundary></span>
</input>
<span class=event-ancestor><div class="volume-slider-container"> <em>4</em></span>
<span class=event-ancestor><input type="range" class="volume-slider"> <em>3</em></span>
<span class="shadow-boundary event-ancestor"><shadow-boundary> <em>2</em></span>
<span class=event-ancestor><div class="slider-thumb"></div> <em>1</em></span>
<span class=shadow-boundary></shadow-boundary></span>
</input>
</div>
</div>
<span class=shadow-boundary></shadow-boundary></span>
</div>
</code></pre>
<p>
At the end of this process, we should have the following set of ancestors and relative targets:
</p>
<table>
<thead>
<tr>
<th>Ancestor</th>
<th>Relative Target</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>...</code></td>
<td><code>div#player</code></td>
</tr>
<tr>
<td><code>div#player</code></td>
<td><code><strong>div#player</strong></code></td>
</tr>
<tr>
<td><code>div#player .controls</code></td>
<td><code>div#player .controls .volume-slider</code></td>
</tr>
<tr>
<td><code>div#player .volume-slider-container</code></td>
<td><code>div#player .controls .volume-slider</code></td>
</tr>
<tr>
<td><code>div#player .controls .volume-slider</code></td>
<td><code><strong>div#player .controls .volume-slider</strong></code></td>
</tr>
<tr>
<td><code>div#player .controls .volume-slider .slider-thumb</code></td>
<td><code><strong>div#player .controls .volume-slider .slider-thumb</strong></code></td>
</tr>
</tbody>
</table>
<p>After we dispatch the <code>mouseover</code> event using these newly computed relative targets, the user decides to move their pointing device over the thumb of the timeline
(<code>#player .timeline .slider-thumb</code>). This triggers both a <code>mouseout</code> event for the volume slider thumb and the <code>mouseover</code> event for the timeline thumb.</p>
<p>Let's study how the <code>relatedTarget</code> value of the volume thumb's <code>mouseout</code> event is affected and whether event escapes out of the player. For this event, the <code>relatedTarget</code> is the timeline thumb (<code>#player .timeline .slider-thumb</code>).</p>
<ol>
<li>We find lowest common ancestor of timeline thumb and volume slider thumb: the controls panel (<code>#player .controls</code>).</li>
<li>Walking up, we look for a <a href="#dfn-shadow-boundary">shadow boundary</a>, and find one just above. This is the <a href="#dfn-lowest-common-boundary">lowest common boundary</a>.</li>
<li>Given that the lowest common boundary exists, we limit event dispatch to the descendants of this boundary.</li>
<li>Starting from the <a href="#dfn-lowest-common-boundary">lowest common boundary</a>, we walk down the ancestors of the timeline thumb, looking for a <a href="shadow-boundary">shadow boundary</a>. We find it just below the timeline (<code>#player .timeline</code>). This is the <a href="#dfn-first-divergent-boundary">first divergent boundary</a>.</li>
<li>We adjust <code>relatedTarget</code> to be the parent of the first divergent boundary, the timeline (<code>#player .timeline</code>). We are now ready to dispatch this event.</li>
</ol>
<pre class="example html"><code>
<div id="player">
<span class="shadow-boundary lowest-common-boundary"><shadow-boundary><em> — lowest common boundary</em></span>
<div class="controls">
<button class="play-button">
<input type="range" class="timeline">
<span class="shadow-boundary first-divergent-boundary"><shadow-boundary><em> — first divergent boundary</em></span>
<div class="slider-thumb"></div>
<span class="shadow-boundary first-divergent-boundary"></shadow-boundary></span>
</input>
<div class="volume-slider-container">
<input type="range" class="volume-slider">
<span class=shadow-boundary><shadow-boundary></span>
<div class="slider-thumb"></div>
<span class=shadow-boundary></shadow-boundary></span>
</input>
</div>
</div>
<span class="shadow-boundary lowest-common-boundary"></shadow-boundary></span>
</div>
</code></pre>
</section>
<h2 id="styles">Styles</h2>
<section>
<p>To enforce <a href="#dfn-upper-boundary-encapsulation">upper-boundary encapsulation</a>, <a href="http://www.w3.org/TR/CSS2/syndata.html#rule-sets">CSS rules</a> declared by the document do not apply in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, unless the <dfn id="dfn-apply-author-styles">apply-author-styles</dfn> flag is set for this subtree. The flag signals that document CSS rules are applicable in the <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>.
<p>Conversely, to enforce <a href="#dfn-lower-boundary-encapsulation">lower-boundary encapsulation</a>, <a href="http://www.w3.org/TR/CSS2/syndata.html#rule-sets">CSS rules</a> from a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a> do not apply to the nodes, distributed to the <a href="#dfn-insertion-point">insertion points</a>.
<p>The <dfn id="dfn-rule-applicability-algorithm">rule applicability algorithm</dfn> is used to determine whether any given rule is applicable to any DOM node, and it <strong>must</strong> be equivalent to processing the following steps:</p>
<div class="algorithm">
<dl>
<dt>Input</dt>
<dd><var>RULE</var>, a CSS rule whose applicability is being determined</dd>
<dd><var>NODE</var>, a DOM node</dd>
<dt>Output</dt>
<dd>Whether <var>RULE</var> must be applied to <var>NODE</var></a>.
</dl>
<ol>
<li>If <var>RULE</var> is not an <a href="http://www.w3.org/TR/CSS2/cascade.html">author style</a>, the rule <strong>is</strong> applicable to <var>NODE</var>.</li>
<li>Otherwise:
<ol>
<li>Let <var>TREE</var> be the DOM subtree to which <var>NODE</var> belongs. The <var>TREE</var> is then the document tree, a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, or some disconnected tree</li>
<li>In the case <var>TREE</var> is a disconnected tree, the rule <strong>is not</strong> applicable to <var>NODE</var>.</li>
<li>In the case <var>TREE</var> is a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>:
<ol>
<li>If <var>TREE</var> has the <a href="#dfn-apply-author-styles">apply-author-styles</a> flag is set for <var>TREE</var>, <var>RULE</var> <strong>is</strong> applicable to <var>NODE</var>.</li>
<li>Otherwise, if <var>RULE</var> is declared with a <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#the-style-element"><code>style</code></a> element:
<ol>
<li>Let <var>STYLE</var> be this style element</li>
<li>If <var>STYLE</var> has a <code>scoped</code> attribute and <var>STYLE</var> is in <var>TREE</var>, then <var>RULE</var> <strong>is</strong> applicable to <var>NODE</var>.</li>
</ol></li>
<li>Otherwise, <var>RULE</var> <strong>is not</strong> applicable to <var>NODE</var>.</li>
</ol>
<li>In the case <var>TREE</var> is a document tree:
<ol>
<li>If <var>RULE</var> is declared in <var>TREE</var>, the rule <strong>is</strong> applicable to <var>NODE</var>.</li>
<li>Otherwise, <var>RULE</var> <strong>is not</strong> applicable to <var>NODE</var>.</li>
</ol></li>
</ol></li>
</ol>
</div>
<p>The effect of this algorithm is that any unscoped styles, declared in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>, are applied <strong>neither</strong> to document <strong>nor</strong> the subtree in which they are declared.</p>
<p>In a document that contains <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>, the CSS properties <strong>must</strong> be inherited from parent nodes, produced using <a href="#dfn-parent-calculation-algorithm">parent calculation algorithm</a>. This requirement has the following effects:</p>
<ul>
<li>the styles of the <a href="#dfn-shadow-host">shadow host</a> are inherited by the children of the <a href="#dfn-shadow-root">shadow root</a></li>
<li>the styles of the <a href="#dfn-insertion-point">insertion point</a> node are inherited by those child nodes of the <a href="#dfn-shadow-host">shadow host</a> that are <a href="#dfn-assign-older-tree">assigned</a> to this <a href="#dfn-insertion-point">insertion point</a></li>
<li>the styles of the <a href="#dfn-shadow-insertion-point">shadow insertion point</a> node are inherited by the child nodes of the <a href="#dfn-shadow-root">shadow root</a> of the <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, distributed to this <a href="#dfn-shadow-insertion-point">shadow insertion point</a></li>
</ul>
<h3 id="css-variables">CSS Variables</h3>
<p>The of <a href="#dfn-shadow-host">shadow host</a> styles being inherited by the children of the <a href="#dfn-shadow-root">shadow root</a> must also apply to <a href="http://dev.w3.org/csswg/css-variables/">CSS Variables</a>. This provides a way for document DOM tree styles to send signals into the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>, and for the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a> to receive these signals with the use of the <a href="http://dev.w3.org/csswg/css-variables/#using-variables"><code>data()</code></a> function.</p>
<h3 id="text-decoration-property"><code>text-decoration</code> Property</h3>
<p>The text decorations, specified by the <a href="http://www.w3.org/TR/CSS2/text.html#lining-striking-props"><code>text-decoration</code></a> property are not propagated from <a href="#dfn-shadow-host">shadow hosts</a> to <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>.</p>
</section>
<h2 id="user-interaction">User Interaction</h2>
<section>
<h3 id="ranges-and-selection">Ranges and Selections</h3>
<p>Since a DOM node in a document tree and a DOM node in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a> never have the same <a href="http://www.w3.org/TR/domcore/#concept-tree-root">root</a>, there may never exist a valid <a href="http://www.w3.org/TR/domcore/#range">DOM range</a> that spans either both a document tree and a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>, or multiple <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>.</p>
<p>Accordingly, <a href="http://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#concept-selection">selections</a> may only exist within one tree, because they are defined by a single <a href="http://www.w3.org/TR/domcore/#range">range</a>. To maintain <a href="#dfn-upper-boundary-encapsulation">upper boundary encapsulation</a>, the selection, returned by the <a href="http://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#dom-window-getselection"><code>window.getSelection()</code></a> method must never return a selection within a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>.</p>
<h3 id="focus-navigation">Focus Navigation</h3>
<p><a href="#dfn-shadow-dom-subtree">Shadow DOM subtrees</a> participate in <a href="#http://www.w3.org/TR/css3-ui/#keyboard">sequential</a> or <a href="#http://www.w3.org/TR/css3-ui/#keyboard">directional</a> focus navigation as part of the document tree. The <a href="#http://www.w3.org/TR/css3-ui/#keyboard">navigation order</a> within the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a> must be determined using the <a href="#dfn-as-rendered">as-rendered</a> structure and is called <dfn id="dfn-shadow-dom-navigation-order">shadow DOM navigation order</dfn>.</p>
<p>For <a href="#http://www.w3.org/TR/css3-ui/#keyboard">sequential focus navigation</a>, the <a href="#dfn-shadow-dom-navigation-order">shadow DOM navigation order</a> sequence must be inserted into the document <a href="#http://www.w3.org/TR/css3-ui/#keyboard">navigation order</a>:</p>
<ol>
<li>immediately after the <a href="#dfn-shadow-host">shadow host</a>, if the shadow host is <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#focusable">focusable</a>; or</li>
<li>in place of the <a href="#dfn-shadow-host">shadow host</a> as if the shadow host were assigned the value of <a href="http://www.w3.org/TR/css3-ui/#keyboard"><code>auto</code></a> for determining its position</a>.</li>
</ol>
<p>For <a href="#http://www.w3.org/TR/css3-ui/#keyboard">directional focus navigation</a>, it is up to the user agent to integrate the <a href="#dfn-shadow-dom-navigation-order">shadow DOM navigation order</a> into the document <a href="#http://www.w3.org/TR/css3-ui/#keyboard">navigation order</a>.</p>
<h3 id="editing">Editing</h3>
<p>The value of the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#attr-contenteditable"><code>contenteditable</code></a> attribute must not propagate from <a href="#dfn-shadow-host">shadow host</a> to its <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>.</p>
<h3 id="assistive-technology">Assistive Technology</h3>
<p>User agents with assistive technology traverse the document tree <a href="#dfn-as-rendered">as rendered</a>, and thus enable full use of of <a href="http://www.w3.org/WAI/PF/aria/">WAI-ARIA</a> semantics in the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>.</p>
</section>
<h2 id="html-elements">HTML Elements in Shadow DOM Subtrees</h2>
<section>
<p>Comparatively, a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a> can be seen as somewhere between <em>just a DOM subtree in a document</em> and a <a href="http://www.w3.org/TR/domcore/#interface-documentfragment">document fragment</a>. Since it is rendered, a shadow DOM subtree aims to retain the traits of a typical DOM subtree in a document. At the same time, it is an encapsulation abstraction, so it has to avoid affecting the document DOM tree. Thus, the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#semantics">HTML elements</a> behave <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/">as specified</a> in the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>, with a few exceptions.</p>
<h3 id="inert-html-elements">Inert HTML Elements</h3>
<p>A subset of <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#semantics">HTML elements</a> behaves as <dfn id="dfn-inert">inert</dfn>, or not part of the document tree. This is consistent how the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#semantics">HTML elements</a> would behave in a <a href="http://www.w3.org/TR/domcore/#interface-documentfragment">document fragment</a>. These elements are:</p>
<ul>
<li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#the-base-element"><code>base</code></a></li>
<li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#the-link-element"><code>link</code></a></li>
</ul>
<p>All other <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#semantics">HTML elements</a> in the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a> behave as if they were part of the document tree, though <a href="#dfn-scoping-constraints">scoped</a> to their subtrees.</p>
<h3 id="html-forms">HTML Forms</h3>
<p>The <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#forms">forms</a> in HTML are scoped at the document level. That is, all <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#the-form-element"><code>form</code></a> elements and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#form-associated-element">form-associated elements</a> are accessible using the document <a href="http://www.w3.org/TR/domcore/#interface-document">DOM object</a>'s <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/dom.html#dom-tree-accessors">tree accessors</a>. Per <a href="#dfn-scoping-constraints">scoping constraints</a>, this excludes elements in the <a href="#dfn-shadow-dom-subtree">shadow DOM subtrees</a>.</p>
<p>Instead, each <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a> scopes its <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#the-form-element"><code>form</code></a> elements and <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#form-associated-element">form-associated elements</a>. Because the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#the-form-element"><code>form</code></a>'s <a href="http://www.w3.org/TR/domcore/#dom-node-ownerdocument"><code>ownerDocument</code></a> is the <a href="#dfn-shadow-host">shadow host</a>'s document, the form submission works <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#form-submission">as specified</a>.</p>
</section>
<h2 id="elements-and-dom-objects">Elements and DOM Objects</h2>
<section>
<h3 id="shadow-root-object"><code>ShadowRoot</code> Object</h3>
<p>The <code>ShadowRoot</code> object represents the <a href="#dfn-shadow-root">shadow root</a>.</p>
<pre><code>
[Constructor(in <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#htmlelement">HTMLElement</a> host) raises (DOMException)]
interface <dfn id="api-shadow-root">ShadowRoot</dfn> : <a href="http://www.w3.org/TR/domcore/#interface-documentfragment">DocumentFragment</a> {
<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#htmlelement">HTMLElement</a> <a href="#api-shadow-root-get-element-by-id">getElementById</a>(in DOMString elementId);
<a href="http://www.w3.org/TR/domcore/#nodelist">NodeList</a> <a href="#api-shadow-root-get-elements-by-class-name">getElementsByClassName</a>(in DOMString tagName);
<a href="http://www.w3.org/TR/domcore/#nodelist">NodeList</a> <a href="#api-shadow-root-get-elements-by-tag-name">getElementsByTagName</a>(in DOMString className);
<a href="http://www.w3.org/TR/domcore/#nodelist">NodeList</a> <a href="#api-shadow-root-get-elements-by-tag-name-ns">getElementsByTagNameNS</a>(DOMString namespace, DOMString localName);
attribute bool <a href="#api-shadow-root-apply-author-styles">applyAuthorStyles</a>;
readonly attribute Element <a href="#api-shadow-root-host">host</a>;
attribute DOMString <a href="#api-shadow-root-inner-html">innerHTML</a>;
}
ShadowRoot implements <a href="http://dev.w3.org/2006/webapi/selectors-api/#nodeselector">NodeSelector</a>;
</code></pre>
<h4 id="shadow-root-attributes"><code>ShadowRoot</code> Attributes</h4>
<dl>
<dt id="api-shadow-root-apply-author-styles"><code>applyAuthorStyles</code> of type <code>bool</code></dt>
<dd>Represents the <a href="#dfn-apply-author-styles">apply-author-styles</a> flag and indicates whether or not the rules in <a href="http://www.w3.org/TR/CSS2/cascade.html">author styles</a> associated with the element's document apply to the shadow DOM subtree. If <code>false</code> (default value), the author styles <strong>are not</strong> applied to the shadow DOM subtree. If <code>true</code>, the author styles <strong>are</strong> applied.</dd>
<dt id="api-shadow-root-host"><code>host</code> of type <code>Element</code>, readonly</dt>
<dd>refers back to the <a href="#dfn-shadow-host">shadow host</a>. This value is never <code>null</code>.</dd>
<dt id="api-shadow-root-inner-html"><code>innerHTML</code> of type <code>DOMString</code></dt>
<dd>represents the markup of <a href="#api-shadow-root"><code>ShadowRoot</code></a>'s contents, and operates <a href="http://html5.org/specs/dom-parsing.html#dom-element-innerhtml">as specified</a>, given <a href="#api-shadow-root"><code>ShadowRoot</code></a> as the <a href="http://html5.org/specs/dom-parsing.html#context-object">context object</a>.</dd>
</dl>
<p>The <a href="http://www.w3.org/TR/domcore/#dom-node-nodetype"><code>nodeType</code></a> attribute of a <a href="#api-shadow-root"><code>ShadowRoot</code></a> instance must return <a href="http://www.w3.org/TR/domcore/#dom-node-document_fragment_node"><code>DOCUMENT_FRAGMENT_NODE</code></a>. Accordingly, the <a href="http://www.w3.org/TR/domcore/#dom-node-nodename"><code>nodeName</code></a> attribute of a <a href="#api-shadow-root"><code>ShadowRoot</code></a> instance must return <code>"#document-fragment"</code>.</p>
<h4 id="shadow-root-methods"><code>ShadowRoot</code> Methods</h4>
<dl>
<dt><code>constructor</code></dt>
<dd>
Creates new shadow root and associates it with the shadow host.
<table>
<thead>
<tr>
<th>Parameter</th>
<th>Type</th>
<th>Nullable</th>
<th>Optional</th>
<th>Description</th>
</tr>
</thead>
<tr>
<td><dfn id="api-shadow-root-constructor-element"><code>element</code></dfn></td>
<td><a href="http://www.w3.org/TR/domcore/#element"><code>Element</code></a></td>
<td>No</td>
<td>No</td>
<td>Element that will be hosting this instance of the shadow DOM subtree.</td>
</tr>
<tbody>
</tbody>
</table>
<div>
<em>Exceptions:</em>
<dl>
<dt><a href="http://www.w3.org/TR/domcore/#dom-domexception-hierarchy_request_err"><code>HIERARCHY_REQUEST_ERR</code></a></dt>
<dd>Thrown when the <code>element</code> parameter is not a valid <a href="http://www.w3.org/TR/domcore/#element"><code>Element</code></a>.
</dl>
</div>
<div>
<em>Returns: a new <code>ShadowRoot</code> instance.</em>
</div>
</dd>
<dt id="api-shadow-root-get-element-by-id"><code>getElementById</code></dt>
<dd>Behaves exactly like <a href="http://www.w3.org/TR/domcore/#dom-document-getelementbyid">document.getElementById</a>, except <a href="#dfn-scoping-constraints">scoped</a> to the shadow DOM subtree.</dd>
<dt id="api-shadow-root-get-elements-by-class-name"><code>getElementsByClassName</code></dt>
<dd>Behaves exactly like <a href="http://www.w3.org/TR/domcore/#dom-document-getelementsbyclassname">document.getElementsByClassName</a>, except <a href="#dfn-scoping-constraints">scoped</a> to the shadow DOM subtree.</dd>
<dt id="api-shadow-root-get-elements-by-tag-name"><code>getElementsByTagName</code></dt>
<dd>Behaves exactly like <a href="http://www.w3.org/TR/domcore/#dom-document-getelementsbytagname">document.getElementsByTagName</a>, except <a href="#dfn-scoping-constraints">scoped</a> to the shadow DOM subtree.</dd>
<dt id="api-shadow-root-get-elements-by-tag-name-ns"><code>getElementsByTagNameNS</code></dt>
<dd>Behaves exactly like <a href="http://www.w3.org/TR/domcore/#dom-document-getelementsbytagnamens">document.getElementsByTagNameNS</a>, except <a href="#dfn-scoping-constraints">scoped</a> to the shadow DOM subtree.</dd>
</dl>
<p>Invoking the <a href="http://www.w3.org/TR/domcore/#dom-node-clonenode"><code>cloneNode()</code></a> method on a <a href="#api-shadow-root"><code>ShadowRoot</code></a> instance must always throw a <a href="http://www.w3.org/TR/domcore/#dom-domexception-data_clone_err"><code>DATA_CLONE_ERR</code></a> exception.</p>
<h3 id="content-element">The <code>content</code> element</h3>
<p>The <dfn id="dfn-content-element"><code>content</code></dfn> element represents an <a href="#dfn-insertion-point">insertion point</a> in the <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>.</p>
<dl>
<dt>Context</dt>
<dd>Where <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#flow-content-0">flow content</a> is expected.</dd>
<dt>Content model</dt>
<dd><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#transparent">Transparent</a></dd>
<dt>Children</dt>
<dd>Anything as <a href="#dfn-fallback-content">fallback content</a></dd>
<dt>Content attributes</dt>
<dd><a href="http://dev.w3.org/html5/spec/Overview.html#global-attributes">Global attributes</a></dd>
<dd>
<dl>
<!-- <dt id="markup-content-apply-shadow-styles"><code>apply-shadow-styles</code>, a <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#boolean-attribute">boolean attribute</a></dt>
<dd>indicates whether or not the rules in the scoped styles, defined in shadow DOM subtree are applied to the host element's children that are inserted in place of this <code>content</code> element. If present, the styles are applied.</dd> -->
<dt id="markup-content-select"><code>select</code>, a <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#comma-separated-tokens">set of comma-separated tokens</a></dt>
<dd>
defines the <a href="#dfn-matching-criteria">matching criteria</a> for distributing child nodes of the <a href="#dfn-host-element">host element</a>. Each token must be a valid <a href="#dfn-selector-fragment">selector fragment</a>. If any token is invalid, the entire value of the <code>select</code> attribute is considered invalid.
</dd>
</dl>
</dd>
<dt>DOM Interface</dt>
<dd>
<pre><code>
interface <dfn id="api-html-content-element">HTMLContentElement</dfn> : <a href="http://dev.w3.org/html5/spec/Overview.html#htmlelement">HTMLElement</a> {<!-- attribute bool <a href="#api-html-content-element-apply-shadow-styles">applyShadowStyles</a>; -->
attribute DOMString <a href="#api-html-content-element-select">select</a>;
}
</code></pre>
<dl>
<dt>Attributes</dt>
<dl>
<!-- <dt id="api-html-content-element-apply-shadow-styles"><code>applyShadowStyles</code> of type <code>bool</code></dt>
<dd>Must <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#reflect">reflect</a> the <a href="#markup-content-apply-shadow-styles">apply-shadow-styles</a> attribute.</dd> -->
<dt id="api-html-content-element-select"><code>select</code> of type <code>DOMString</code></dt>
<dd>
<dd>Must <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#reflect">reflect</a> the <a href="#markup-content-select">select</a> attribute.</dd>
</dd>
</dd>
</dl>
</dl>
</dl>
<h3 id="shadow-element">The <code>shadow</code> element</h3>
<p>The <dfn id="dfn-shadow-element"><code>shadow</code></dfn> element represents an <a href="#dfn-shadow-insertion-point">shadow insertion point</a> in a <a href="#dfn-shadow-dom-subtree">shadow DOM subtree</a>.</p>
<dl>
<dt>Context</dt>
<dd>Where <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#flow-content-0">flow content</a> is expected.</dd>
<dt>Content model</dt>
<dd><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#transparent">Transparent</a></dd>
<dt>Children</dt>
<dd>Anything as <a href="#dfn-fallback-content">fallback content</a></dd>
<dt>Content attributes</dt>
<dd><a href="http://dev.w3.org/html5/spec/Overview.html#global-attributes">Global attributes</a></dd>
<dt>DOM Interface</dt>
<dd>
<pre><code>
interface <dfn id="api-html-shadow-element">HTMLShadowElement</dfn> : <a href="http://dev.w3.org/html5/spec/Overview.html#htmlelement">HTMLElement</a> {
}
</code></pre>
</dl>
</dl>
<h3 id="shadow-dom-example">Shadow DOM Example</h3>
<p>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:</p>
<pre class="prettyprint"><code>
<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"><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/4">Awesome story</a></li>
<li class="breaking"><a href="//example.com/stories/5">Horrible story</a></li>
</ul>
</code></pre>
<p>To organize the stories, Bob decides to use <strong>shadow DOM</strong>. 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 <a href="http://en.wikipedia.org/wiki/List_of_coffee_beverages#Green_Eye">Green Eye</a>, he quickly mocks up the following shadow DOM subtree, to be hosted by the <code>ul</code> element:</p>
<pre class="prettyprint"><code>
<div class="breaking">
<ul>
<content select=".breaking"></content> <!-- insertion point for breaking news -->
</ul>
</div>
<div class="other">
<ul>
<content></content> <!-- insertion point for the rest of the news -->
</ul>
</div>
</code></pre>
<p>Bob then styles the newborn widget according to comps from the designer by adding this to the shadow DOM subtree mockup:</p>
<pre class="prettyprint"><code>
<style scoped>
div.breaking {
color: Red;
font-size: 20px;
border: 1px dashed Purple;
}
div.other {
padding: 2px 0 0 0;
border: 1px solid Cyan;
}
</style>
</code></pre>
<p>While pondering if his company should start looking for a new designer, Bob converts the mockup to code:</p>
<pre class="prettyprint"><code>
function createStoryGroup(className, contentSelector)
{
var group = document.createElement('div');
group.className = className;
// Empty string in select attribute or absence thereof work the same, so no need for special handling.
group.innerHTML = '<ul><content select="' + contentSelector + '"></content></ul>';
return group;
}
function createStyle()
{
var style = document.createElement('style');
style.scoped = true;
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 makeShadowSubtree(storyList)
{
var root = new ShadowRoot(storyList);
root.appendChild(createStyle());
root.appendChild(createStoryGroup('breaking', '.breaking'));
root.appendChild(createStoryGroup('other', ''));
}
document.addEventListener('DOMContentLoaded', function {
[].forEach.call(document.querySelectorAll('ul.stories'), makeShadowSubtree);
});
</code></pre>
<p>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 <a href="http://en.wikipedia.org/wiki/World_of_Warcraft">WoW</a>.</p>
<p>A few months pass.</p>
<p>It's election time. With Bob at his annual conference, Alice is charged with adding <strong>another</strong>, temporary box to the news widget, filled with election-related stories. Alice studies Bob's code, reads up on the shadow DOM spec and realizes that, thanks to multiple shadow DOM subtree support, she doesn't have to touch his code. As usual, her solution is elegant and simple, fitting neatly right under Bob's code:</p>
<pre class="prettyprint"><code>
// TODO(alice): BEGIN -- DELETE THIS CODE AFTER ELECTIONS ARE OVER.
var ELECTION_BOX_REMOVAL_DEADLINE = ...;
function createElectionStyle()
{
var style = document.createElement('style');
style.scoped = true;
// TODO(alice): Check designer's desk for hallucinogens.
style.textContent = 'div.election { color: Magenta;font-size: 24px; border: 2px dotted Fuchsia; }';
return style;
}
function makeElectionShadowSubtree(storyList)
{
var root = new ShadowRoot(storyList);
// Add and style election story box.
root.appendChild(createElectionStyle());
root.appendChild(createStoryGroup('election', '.election'));
// Insert Bob's shadow tree under the election story box.
root.appendChild(document.createElement('shadow'));
}
if (Date.now() < ELECTION_BOX_REMOVAL_DEADLINE) {
document.addEventListener('DOMContentLoaded', function {
[].forEach.call(document.querySelectorAll('ul.stories'), makeElectionShadowSubtree);
});
}
// TODO(alice): END -- DELETE THIS CODE AFTER ELECTIONS ARE OVER.
</code></pre>
<p>Using the <code>shadow</code> element allows Alice to compose Bob's widget <strong>inside</strong> of hers—without having to change a line of production code. Smiling to herself, Alice realizes that Bob may have come up with a way to keep the document markup clean, but <strong>she</strong> is the one who takes the cake for using shadow DOM subtree composition in such a cool way.</p>
</section>
<h2 id="acknowledgements">Acknowledgements</h2>
<section>
<p><span class="vcard">David Hyatt</span> developed <a href="http://dev.w3.org/2006/xbl2/">XBL 1.0</a>, and <span class="vcard">Ian Hickson</span> co-wrote <a href="http://dev.w3.org/2006/xbl2/">XBL 2.0</a>. These documents provided tremendous insight into the problem of functional encapsulation and greatly influenced this specification.</p>
<p><span class="vcard">Alex Russell</span> 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.</p>
<p><span class="vcard">Dominic Cooney</span>, <span class="vcard">Hajime Morrita</span>, and <span class="vcard">Roland Steiner</span> worked tirelessly to scope the problem of functional encapsulation within the confines of the Web platform and provided a solid foundation for this document.</p>
<p>The editor would also like to thank <span class="vcard">Alex Komoroske</span>, <span class="vcard">Brian Kardell</span>, <span class="vcard">Darin Fisher</span>, <span class="vcard">Edward O'Connor</span>, <span class="vcard">Elisée Maurer</span>, <span class="vcard">Erik Arvidsson</span>, <span class="vcard">Hayato Ito</span>, <span class="vcard">Jonas Sicking</span>, <span class="vcard">Malte Ubl</span>, <span class="vcard">Olli Pettay</span>, <span class="vcard">Rafael Weinstein</span>, <span class="vcard">Sam Dutton</span>, and <span class="vcard">Tab Atkins</span> for their comments and contributions to this specification.</p>
<p>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.</p>
</section>
</article>
</body>
</html>