Skip to content

Commit 91db652

Browse files
committed
Initial rough draft/notes for Styling post
1 parent d75620d commit 91db652

File tree

1 file changed

+188
-1
lines changed

1 file changed

+188
-1
lines changed

learn/components/styling.md

Lines changed: 188 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,191 @@ title: Styling
33
order: 5
44
---
55

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

Comments
 (0)