m y t e m p l a t e " h i d d e n > < i m g s r c = " l o g o . p n g " > < d i v c l a s s = " c o m m e n t " > < / d i v > < / d i v > We can clone the DOM Nothing is rendered Not inert, network request is made for the image Styling is painful, all styles must be prefixed with # m y t e m p l a t e
d = " m y t e m p l a t e " t y p e = " t e x t / x - h a n d l e b a r s - t e m p l a t e " > < / s c r i p t > < i m g s r c = " l o g o . p n g " > < d i v c l a s s = " c o m m e n t " > < / d i v > Nothing rendered, < s c r i p t > is d i s p l a y : n o n e ; by default It's inert (yay!), JS isn't parsed because of its type Security issues, run-time string of user-supplied data can easily lead to XSS vulnerabilities
l a t e i d = " m y t e m p l a t e " > < i m g s r c = " p a t h / t o / s o u r c e . p n g " a l t = " g r e a t i m a g e " > < d i v c l a s s = " c o m m e n t " > < / d i v > < / t e m p l a t e > Clonable DOM Parsed, not rendered Stylesheets/Images aren't loaded, media isn't played, scripts don't run
c o n t e n t document fragment. v a r t = d o c u m e n t . q u e r y S e l e c t o r ( ' # m y t e m p l a t e ' ) ; t . c o n t e n t . q u e r y S e l e c t o r ( ' i m g ' ) . s r c = ' l o g o . p n g ' ; d o c u m e n t . b o d y . a p p e n d C h i l d ( t . c o n t e n t . c l o n e N o d e ( t r u e ) ) ; Demo
S h a d o w R o o t ( ) creates a shadow root on a host element. < b u t t o n > H e l l o W o r l d ! < / b u t t o n > v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' b u t t o n ' ) ; v a r s h a d o w R o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; s h a d o w R o o t . t e x t C o n t e n t = ' H e l l o J s i s t ! ' ; Demo
into your Shadow DOM (. i n n e r H T M L , . a p p e n d C h i l d ( ) ...). v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' # h o s t ' ) ; v a r s h a d o w R o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; v a r p = d o c u m e n t . c r e a t e E l e m e n t ( ' p ' ) ; p . i n n e r H T M L = ' T h i s i s H T M L c o d e ' ; / * * * B o t h w o r k * / s h a d o w R o o t . i n n e r H T M L = ' < p > T h i s i s H T M L c o d e < / p > ' ; s h a d o w R o o t . a p p e n d C h i l d ( p ) ;
learned. < t e m p l a t e i d = " c u s t o m - t e m p l a t e " > < p > T h i s i s H T M L C o d e < / p > < / t e m p l a t e > v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' # h o s t ' ) ; v a r s h a d o w R o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; v a r t = d o c u m e n t . q u e r y S e l e c t o r ( ' # c u s t o m - t e m p l a t e ' ) ; s h a d o w R o o t . a p p e n d C h i l d ( t . c o n t e n t . c l o n e N o d e ( t r u e ) ) ;
l a t e i d = " s p e c i a l - b u t t o n - t e m p l a t e " > < s t y l e > < / s t y l e > < b u t t o n c l a s s = " s p e c i a l - b u t t o n " > S p e c i a l B u t t o n ! < / b u t t o n > < / t e m p l a t e > . s p e c i a l - b u t t o n { b a c k g r o u n d : # b a d a 5 5 ; c o l o r : r e d ; p a d d i n g : 1 e m ; b o r d e r - r a d i u s : 0 . 3 e m ; f o n t - s i z e : 1 e m ; }
d = " s p e c i a l - b u t t o n - t e m p l a t e " > < s t y l e > < / s t y l e > < b u t t o n c l a s s = " s p e c i a l - b u t t o n " > S p e c i a l B u t t o n ! < / b u t t o n > < / t e m p l a t e > . s p e c i a l - b u t t o n { b a c k g r o u n d : # b a d a 5 5 ; c o l o r : r e d ; p a d d i n g : 1 e m ; b o r d e r - r a d i u s : 0 . 3 e m ; f o n t - s i z e : 1 e m ; }
d = " s p e c i a l - b u t t o n - t e m p l a t e " > < s t y l e > < / s t y l e > < b u t t o n c l a s s = " s p e c i a l - b u t t o n " > < c o n t e n t > < / c o n t e n t > < / b u t t o n > < / t e m p l a t e > . s p e c i a l - b u t t o n { b a c k g r o u n d : # b a d a 5 5 ; c o l o r : r e d ; p a d d i n g : 1 e m ; b o r d e r - r a d i u s : 0 . 3 e m ; f o n t - s i z e : 1 e m ; } Demo
uses CSS selectors to specify where children are projected. < d i v i d = " h o s t " > < h 1 > M y T i t l e < / h 1 > < h 2 > M y S u b t i t l e < / h 2 > < d i v > . . . o t h e r c o n t e n t . . . < / d i v > < / d i v > < h g r o u p > < c o n t e n t s e l e c t = " h 2 " > < / c o n t e n t > < c o n t e n t s e l e c t = " h 1 : f i r s t - c h i l d " > < / c o n t e n t > < / h g r o u p >
enables style encapsulation for free. Styles are scoped to shadow root < d i v > < h 3 > L i g h t D O M < / h 3 > < / d i v > < s c r i p t > v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' d i v ' ) . c r e a t e S h a d o w R o o t ( ) ; h o s t . i n n e r H T M L = ' < s t y l e > h 3 { c o l o r : r e d ; } < / s t y l e > ' + ' < h 3 > S h a d o w D O M < / h 3 > ' ; < / s c r i p t > Shadow DOM
us to style the element hosting a shadow tree. < b u t t o n > M y b u t t o n < / b u t t o n > < s c r i p t > v a r b u t t o n = d o c u m e n t . q u e r y S e l e c t o r ( ' b u t t o n ' ) ; v a r h o s t = b u t t o n . c r e a t e S h a d o w R o o t ( ) ; h o s t . i n n e r H T M L = ' < s t y l e > ' + ' : h o s t { t e x t - t r a n s f o r m : u p p e r c a s e ; } ' + ' < / s t y l e > ' + ' < c o n t e n t > < / c o n t e n t > ' ; < / s c r i p t > MY BUTTON
n t e x t ( s e l e c t o r ) - Matches if host element or any of its ancestors match s e l e c t o r < d i v c l a s s = " t h e m e - n a m e " > < x - f o o > < / x - f o o > < / d i v > : h o s t - c o n t e x t ( . t h e m e - n a m e ) { / * s t y l e s * / }
to cross the shadow boundaries and style Shadow DOM from the outside world. : : s h a d o w - matches the shadow root itself / d e e p / - Crosses into any number of shadow trees
< s t y l e > < / s t y l e > < d i v i d = " h o s t " > < s p a n > L i g h t D O M < / s p a n > < / d i v > # h o s t : : s h a d o w s p a n { c o l o r : r e d ; } v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' d i v ' ) ; v a r r o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; r o o t . i n n e r H T M L = ' < s p a n > S h a d o w D O M < / s p a n > ' + ' < c o n t e n t > < / c o n t e n t > ' ; Shadow DOMLight DOM
having multiple levels of Shadow DOM (very common when working with Custom Elements. x - t a b s / d e e p / x - p a n e l { / * s t y l e s * / } ^ Select all x - p a n e l elements that are descendents of x - t a b anywhere in the tree.
t . r e g i s t e r E l e m e n t ( ) let's you create custom elements. v a r M y E l e m e n t = d o c u m e n t . r e g i s t e r E l e m e n t ( ' m y - e l e m e n t ' ) ; d o c u m e n t . b o d y . a p p e n d C h i l d ( n e w M y E l e m e n t ( ) ) ; Or with an optional prototype v a r M y E l e m e n t = d o c u m e n t . r e g i s t e r E l e m e n t ( ' m y - e l e m e n t ' , { p r o t o t y p e : O b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) } ) ;
L [ t y p e ] E l e m e n t and add e x t e n d s property accordingly. v a r M e g a B u t t o n = d o c u m e n t . r e g i s t e r E l e m e n t ( ' m e g a - b u t t o n ' , { p r o t o t y p e : O b j e c t . c r e a t e ( H T M L B u t t o n E l e m e n t . p r o t o t y p e , { / * n e w A P I s * / } ) , e x t e n d s : ' b u t t o n ' } ) ; < b u t t o n i s = " m e g a - b u t t o n " > < / b u t t o n > Custom elements that inherit from native elements are called type extension custom elements.
e m e n t > < / m y - e l e m e n t > Via DOM APIs: v a r m y E l e m e n t = d o c u m e n t . c r e a t e E l e m e n t ( ' m y - e l e m e n t ' ) ; Using n e w : v a r m y E l e m e n t = n e w M y E l e m e n t ( ) ; d o c u m e n t . b o d y . a p p e n d C h i l d ( m y E l e m e n t ) ;
C a l l b a c k - instance of the element is created a t t a c h e d C a l l b a c k - instance was inserted into the document d e t a c h e d C a l l b a c k - instance was removed into the document a t t r i b u t e C h a n g e d C a l l b a c k - attribute was added, removed or updated
b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) ; p r o t o . c r e a t e d C a l l b a c k = f u n c t i o n ( ) { . . . } ; p r o t o . a t t a c h e d C a l l b a c k = f u n c t i o n ( ) { . . . } ; v a r X F o o = d o c u m e n t . r e g i s t e r E l e m e n t ( ' x - f o o ' , { p r o t o t y p e : p r o t o } ) ;
b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) ; p r o t o . c r e a t e d C a l l b a c k = f u n c t i o n ( ) { t h i s . i n n e r H T M L = ' < p > H T M L g o e s h e r e < / p > ' ; } ; v a r X F o o = d o c u m e n t . r e g i s t e r E l e m e n t ( ' x - f o o ' , { p r o t o t y p e : p r o t o } ) ;
b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) ; p r o t o . c r e a t e d C a l l b a c k = f u n c t i o n ( ) { v a r t = d o c u m e n t . q u e r y S e l e c t o r ( ' # s d t e m p l a t e ' ) ; v a r c l o n e = t . c o n t e n t . c l o n e N o d e ( t r u e ) ; t h i s . c r e a t e S h a d o w R o o t ( ) . a p p e n d C h i l d ( c l o n e ) ; } ; v a r X F o o = d o c u m e n t . r e g i s t e r E l e m e n t ( ' x - f o o ' , { p r o t o t y p e : p r o t o } ) ;
loaded: < s c r i p t s r c > - For JavaScript < l i n k r e l = " s t y l e s h e e t " > - For Stylesheets < i m g > , < v i d e o > , < a u d i o > ...
e > - super heavy, super restrictive, frustrating to script in/out A J A X - x h r . r e s p o n s e T y p e = " d o c u m e n t " , wtf? We need JS to load HTML? Hacks - embedded in strings, hidden as comments
= " s t y l e s h e e t " h r e f = " b o o t s t r a p . c s s " > < l i n k r e l = " s t y l e s h e e t " h r e f = " f o n t s . c s s " > < s c r i p t s r c = " j q u e r y . j s " > < / s c r i p t > < s c r i p t s r c = " b o o t s t r a p . j s " > < / s c r i p t > < s c r i p t s r c = " b o o t s t r a p - t o o l t i p . j s " > < / s c r i p t > < s c r i p t s r c = " b o o t s t r a p - d r o p d o w n . j s " > < / s c r i p t >
n k = d o c u m e n t . q u e r y S e l e c t o r ( ' l i n k [ r e l = " i m p o r t " ] ' ) ; v a r c o n t e n t = l i n k . i m p o r t ; v a r e l = c o n t e n t . q u e r y S e l e c t o r ( ' . w i d g e t ' ) ; d o c u m e n t . b o d y . a p p e n d C h i l d ( e l ) ; Content is inert until cloned into the DOM!
e r - e l e m e n t n a m e = " f o o - e l e m e n t " c o n s t r u c t o r = " F o o E l e m e n t " > < t e m p l a t e > < ! - - s h a d o w D O M h e r e - - > < p > T h i s i s a f o o - e l e m e n t . < / p > < / t e m p l a t e > < s c r i p t > < / s c r i p t > < / p o l y m e r - e l e m e n t > P o l y m e r ( { / / p r o p e r t i e s a n d m e t h o d s h e r e } ) ;
g = x t a g . c r e a t e F r a g m e n t ( ' < p > T h i s i s a f o o - e l e m e n t . < / p > ' ) ; x t a g . r e g i s t e r ( ' f o o - e l e m e n t ' , { l i f e c y c l e : { c r e a t e d : f u n c t i o n ( ) { t h i s . a p p e n d C h i l d ( f r a g . c l o n e N o d e ( t r u e ) ) ; } } } ) ;
. r e g i s t e r ( ' m y - e l e m e n t ' , { l i f e c y c l e : { c r e a t e d : f u n c t i o n ( ) { v a r t p l = d o c u m e n t . q u e r y S e l e c t o r ( ' # m y - t e m p l a t e ' ) ; v a r s h a d o w = t h i s . c r e a t e S h a d o w R o o t ( ) s h a d o w . a p p e n d C h i l d ( t p l . c o n t e n t . c l o n e N o d e ( t r u e ) ) ; } } } ) ;