@@ -3,4 +3,191 @@ title: Styling
3
3
order : 5
4
4
---
5
5
6
- {% stub %}
6
+ ## (Introduction)
7
+
8
+ - Web Components have powerful styling capabilities.
9
+ - _ Let’s start off positive, even if it’s going to get a little
10
+ hairy._
11
+ - Shadow DOM encapsulation makes Web Component styles generally easier
12
+ to author.
13
+ - Elements within a shadow tree cannot be directly selected by styles
14
+ declared outside of it. Conversely, elements outside of a shadow
15
+ tree cannot be directly selected by styles declared within it.
16
+ - Web Component authors need not worry about naming conflicts for CSS
17
+ classes outside of a shadow tree.
18
+ - Web Component authors can use less specific selectors without much
19
+ worry as there are generally less elements used within a shadow
20
+ tree.
21
+ - Encapsulation is not isolation. Styles set outside of a shadow tree
22
+ can indirectly influence styles within a shadow tree.
23
+ - _ Use this to transition to the next section..._
24
+
25
+ ## Shadow Hosts and CSS Inheritance
26
+
27
+ It is very important to understand the role of a ** shadow host** .
28
+
29
+ ### What is a Shadow Host
30
+
31
+ - A ** shadow host** is an element with a ** shadow tree** and it is not
32
+ the ** shadow root** . If your Web Component uses the Shadow DOM, the
33
+ element itself is a shadow host.
34
+ - The ** shadow root** is a non-element node that cannot be selected
35
+ or styled since it’s featureless.
36
+ - A ** shadow host** is not a part of a ** shadow tree** . It exists
37
+ _ outside_ of a shadow tree and therefore cannot be selected directly
38
+ by styles declared within its shadow tree (i.e. referencing the tag
39
+ name with a type selector will not select the host — only nested
40
+ elements of that type). We can select it with the ` :host `
41
+ pseudo-class and its functional counterpart ` :host() ` — more on that
42
+ later.
43
+ - ` :host ` when combined with relative selectors will be based on the
44
+ shadow root within the shadow tree and not in the light tree.
45
+ - Being a part of the DOM outside of a shadow tree, the host element
46
+ can be subject to styles declared in that context.
47
+
48
+ ### CSS Inheritance
49
+
50
+ - ** A shadow host’s styles become the point of inheritance for all
51
+ top-level elements within a shadow tree.**
52
+ - For example, setting ` font-family: sans-serif ` for the ` html `
53
+ element in a document-level stylesheet can affect our Web
54
+ Component since ` font-family ` is generally an inherited property
55
+ for most elements, including an autonomous custom element by default.
56
+ - Inheritance is one way that styles from an oustide DOM can enter
57
+ into a shadow tree.
58
+
59
+ #### Custom Properties
60
+
61
+ - CSS Custom Properties inherit by default.
62
+ - _ Could be a subheading_
63
+ - There is an upcoming feature to CSS which allows CSS authors to
64
+ configure whether a custom property will inherit by default (see
65
+ ` @property ` ).
66
+
67
+ ## The Order of Precedence
68
+
69
+ ### Kinda like user-agent stylesheets...
70
+
71
+ - Styles set inside of a shadow tree work similar to a user-agent
72
+ stylesheet.
73
+ - For example, inside a shadow tree you can set your custom
74
+ element’s default styles using the ` :host ` pseudo-class. If there
75
+ are styles declared for the element outside of the shadow tree,
76
+ those will win. It might seem counter intuitive at first,
77
+ especially when you compare the strength of the specificity.
78
+ - ** Specificity does not matter between DOM trees.**
79
+ - ` :host ` technically has a specificity value of 0,1,0.
80
+ - ` fancy-button ` has a specificity score of 0,0,1,
81
+ - The latter wins even if you wrap it with ` :where() ` which
82
+ decreases it to 0,0,0.
83
+
84
+ ### Using ` !important ` to prevent outside styling
85
+
86
+ The only way to completely prevent shadow tree styles from being
87
+ overriden is to use ` !important ` .
88
+
89
+ ``` html
90
+ <style >
91
+ fancy-button {
92
+ font-size : 2rem ; /* Wins */
93
+ color : deeppink ; /* Loses */
94
+ font-family : serif !important ; /* Loses */
95
+ }
96
+ </style >
97
+ <fancy-button >
98
+ <template shadowroot =" open" >
99
+ <style >
100
+ :host {
101
+ font-size : 1rem ; /* Loses */
102
+ color : dodgerblue !important ; /* Wins */
103
+ font-family : sans-serif !important ; /* Wins */
104
+ }
105
+ </style >
106
+ <slot ></slot >
107
+ Shadow text
108
+ </template >
109
+ Slotted Text
110
+ </fancy-button >
111
+ ```
112
+
113
+ ## Slots
114
+
115
+ When an element becomes a shadow host, it renders its shadow tree
116
+ instead of its light tree. Slots can be used in a shadow tree to render
117
+ elements from the light tree. We can further style these elements using
118
+ the ` ::slotted() ` pseudo-element function.
119
+
120
+ - The order of precedence applies the same to slotted elements.
121
+ - Only the slotted element is exposed for styling. You cannot use
122
+ combinators to select relative elements.
123
+ - Pseudo-classes like ` :first-child ` , ` :nth-of-type() ` work, however,
124
+ the order of the elements is based on the light tree and not where
125
+ they’ve been slotted in the shadow tree.
126
+
127
+ ## Parts
128
+
129
+ The CSS Shadow Parts API is a way to expose elements within a shadow
130
+ tree to be styled by outside CSS.
131
+
132
+ ``` html
133
+ <fancy-button >
134
+ <template shadowroot =" open" >
135
+ <button part =" the-actual-button" >
136
+ <slot name =" icon" ></slot >
137
+ <slot ></slot >
138
+ </button >
139
+ </template >
140
+ Fancy
141
+ </fancy-button >
142
+ ```
143
+
144
+ The inner button element can be referenced by styles declared outside of
145
+ the shadow tree using the ` ::part() ` pseudo-element function. The ` part `
146
+ attribute is set the same way classes are set on an element. An element
147
+ can be multiple parts.
148
+
149
+ ``` css
150
+ fancy-button ::part(the-actual-button ) {
151
+ color : wheat ;
152
+ }
153
+ ```
154
+
155
+ - Parts follow the order of precedence as well.
156
+ - Similar to slots, relative combinators cannot be used to select
157
+ unexposed elements.
158
+ - Descedents of parts are still subject to inheritance. So parts
159
+ effectively become more windows of influence for a shadow tree’s
160
+ styles.
161
+
162
+ ### Using ` exportparts ` to expose parts from a nested custom element
163
+
164
+ Use the ` exportparts ` attribute on the nested custom element to expose
165
+ its parts from the current shadow host for styling. The attribute takes
166
+ a comma separated list of part names. Names can be reassigned to prevent
167
+ conflict using a colon.
168
+
169
+ ## How to declare styles in the Shadow DOM
170
+
171
+ ### ` <style> `
172
+
173
+ ### ` <link rel="stylesheet"> `
174
+
175
+ - Maybe note that `<link rel="preload" href="/path-to-stylesheet"
176
+ as="style">` can be used to avoid FOUC and to parallelize the network
177
+ waterfall. You’d only want to use this if the component is used in the
178
+ initial render.
179
+
180
+ ### Constructed stylesheets
181
+
182
+ - Note that Safari does not support these.
183
+
184
+ ## (Stuff about at-rules)
185
+
186
+ - ` @keyframes `
187
+ - Can a ` ::slotted() ` element (technically in the light tree) use a
188
+ keyframe declared in the a shadow tree?
189
+ - iirc the results are mixed.
190
+ - ` @font-face `
191
+
192
+
193
+ ## (Putting it all together and best practices)
0 commit comments