Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c359028

Browse filesBrowse files
authored
docs: add css layers adr (#5916)
1 parent 445b5d5 commit c359028
Copy full SHA for c359028

File tree

1 file changed

+120
-0
lines changed
Filter options

1 file changed

+120
-0
lines changed
+120Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# CSS Layers
2+
3+
## Status
4+
5+
| Stage | Status |
6+
| -------- | ------ |
7+
| Approved | 🚧 |
8+
| Adopted | 🚧 |
9+
10+
## Context
11+
12+
During our transition to CSS Modules, we made use of the `:where()` pseudo-class
13+
to help create stable selector specificity. Now that teams could provide a
14+
`className` to a component we needed to ensure that selectors that we used in a
15+
component had matching specificity to the given class name, otherwise we would
16+
run into the risk of accidentally shipping a breaking change.
17+
18+
For example, consider setting a `color` on a component:
19+
20+
```css
21+
/* v1.0.0 of a component */
22+
.Component {
23+
color: var(--fgColor-default);
24+
}
25+
26+
/* The override class placed on the same element as the component class */
27+
.override {
28+
color: var(--fgColor-muted);
29+
}
30+
```
31+
32+
Now, in a future version of the component, we increase the specificity of the
33+
selector:
34+
35+
```css
36+
/* v1.1.0 of a component */
37+
.Component[data-variant='default'] {
38+
color: var(--fgColor-default);
39+
}
40+
```
41+
42+
With this change, the `override` class will no longer override the color as it
43+
did in the previous version.
44+
45+
To mitigate this, we can use the `:where()` pseudo-class to limit the
46+
specificity of our selectors to `0,1,0`, for example:
47+
48+
```css
49+
.Component:where([data-variant='default']) {
50+
color: var(--fgColor-default);
51+
}
52+
53+
/* Or with nesting: */
54+
.Component {
55+
&:where([data-variant='default']) {
56+
color: var(--fgColor-default);
57+
}
58+
}
59+
```
60+
61+
However, this approach requires us to use the `:where()` pseudo-class in every
62+
selector where we would like to have stable specificity. This can lead to issues
63+
where you may forget to use the `:where()` pseudo-class in a selector, or where
64+
you are not sure if you need to use it or not so you add it everywhere.
65+
66+
## Decision
67+
68+
Instead of making use of the `:where()` pseudo-class in every selector, we will
69+
use a CSS layer to create a stable selector specificity. This will allow us to
70+
author our CSS without having to worry about the specificity of each selector.
71+
72+
Our example from earlier would now look like:
73+
74+
```css
75+
@layer primer.components.component {
76+
.Component[data-variant='default'] {
77+
color: var(--fgColor-default);
78+
}
79+
}
80+
```
81+
82+
Using a CSS layer in this way allows us to author our CSS without having to
83+
consider whether or not to use `:where()`. This is due to the nature of CSS
84+
layers where if two layers are targetting the same element, the last layer
85+
targetting that element will take precedence.
86+
87+
Since we are moving our CSS into a CSS layer, this means that later layers (in
88+
particularly the anonymous layer) will take precedence when two rules are
89+
matching the same element. For example:
90+
91+
```css
92+
@layer primer.components.component {
93+
.Component[data-variant='default'] {
94+
color: var(--fgColor-default);
95+
}
96+
}
97+
98+
.override {
99+
color: var(--fgColor-muted);
100+
}
101+
```
102+
103+
It's important to note that even though the `override` class has lower
104+
specificity, it will still take precedence over the
105+
`.Component[data-variant='default']` due to how CSS layers work.
106+
107+
### Impact
108+
109+
This decision will impact our component styles that are authored with CSS
110+
Modules. For each file, we will need to update the module to be wrapped in a CSS
111+
layer. This layer will be named following the convention:
112+
`primer.components.<component-name>`
113+
114+
In addition, selectors that use `:where()` may now be refactored to no longer
115+
use the `:where()` pseudo-class.
116+
117+
## Unresolved questions
118+
119+
- Is it possible for stylelint to have a rule to guarantee the presence of a CSS
120+
layer in a CSS Module file for a component?

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.