Skip to content

Commit 6733f3c

Browse files
authored
perf(css): remove universal * subjects and expand merged :is() selector lists (#4095)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 48f5900 commit 6733f3c

6 files changed

Lines changed: 179 additions & 123 deletions

File tree

.changeset/fast-pumas-juggle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/view-components": patch
3+
---
4+
5+
Improve CSS style-recalc performance by removing selectors with universal subjects and expanding merged `:is()` selector lists so the browser can fast-reject them. Affects `autocomplete-item`, `Popover-message--*`, `breadcrumb-item`, and `FormControl-checkbox-wrap`/`FormControl-radio-wrap` styles.

app/components/primer/alpha/auto_complete.pcss

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,13 @@
9292
background-color: var(--overlay-bgColor);
9393
border: 0;
9494

95+
/* `color` is inherited, so setting it on the item recolors descendants
96+
** without a universal `… *` descendant rule (which forces a slow
97+
** style-recalc match attempt against every element on the page). */
9598
&:hover {
9699
color: var(--fgColor-onEmphasis);
97100
text-decoration: none;
98101
background-color: var(--bgColor-accent-emphasis);
99-
100-
/* Inherit color on all child elements to ensure enough contrast */
101-
& * {
102-
color: inherit !important;
103-
}
104102
}
105103

106104
&.selected,
@@ -109,10 +107,5 @@
109107
color: var(--fgColor-onEmphasis);
110108
text-decoration: none;
111109
background-color: var(--bgColor-accent-emphasis);
112-
113-
/* Inherit color on all child elements to ensure enough contrast */
114-
& * {
115-
color: inherit !important;
116-
}
117110
}
118111
}

app/components/primer/alpha/text_field.pcss

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
}
7575

7676
/* shared among all form control components (input, select, textarea, checkbox, radio) */
77+
/* stylelint-disable nesting-selector-no-missing-scoping-root */
7778
@define-mixin Field {
7879
color: var(--fgColor-default);
7980
background-color: var(--bgColor-default);
@@ -114,6 +115,7 @@
114115
@mixin focusBoxShadowInset;
115116
}
116117
}
118+
/* stylelint-enable nesting-selector-no-missing-scoping-root */
117119

118120
/* TextInput structure
119121
** ===================
@@ -634,18 +636,21 @@
634636
grid-template-columns: min-content auto;
635637
gap: var(--base-size-8);
636638

637-
& .FormControl-checkbox-labelWrap,
638-
& .FormControl-radio-labelWrap {
639-
display: flex;
640-
flex-direction: column;
641-
gap: var(--base-size-4);
642-
}
643-
644639
& .FormControl-label {
645640
cursor: pointer;
646641
}
647642
}
648643

644+
/* Expanded per-class so the subject buckets by a single class during style
645+
** recalc, instead of compiling to a merged `:is(...)` subject that Blink
646+
** cannot fast-reject. */
647+
.FormControl-checkbox-wrap .FormControl-checkbox-labelWrap,
648+
.FormControl-radio-wrap .FormControl-radio-labelWrap {
649+
display: flex;
650+
flex-direction: column;
651+
gap: var(--base-size-4);
652+
}
653+
649654
.FormControl-radio-group-wrap {
650655
& fieldset {
651656
padding: 0;

app/components/primer/beta/breadcrumbs.pcss

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
}
1616
}
1717

18-
.breadcrumb-item-selected,
19-
.breadcrumb-item[aria-current]:not([aria-current='false']) {
20-
&::after {
21-
content: none;
22-
}
18+
/* Expanded per-class so each selector buckets by its own class during style
19+
** recalc, instead of compiling to a merged `:is(...)` that Blink cannot
20+
** fast-reject. */
21+
.breadcrumb-item-selected::after,
22+
.breadcrumb-item[aria-current]:not([aria-current='false'])::after {
23+
content: none;
2324
}
2425

2526
/* stylelint-disable-next-line selector-max-type */

app/components/primer/beta/popover.pcss

Lines changed: 132 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
border-radius: var(--borderRadius-medium);
1818

1919
/* adding !important to override utility classes used in dotcom */
20+
/* stylelint-disable-next-line primer/box-shadow */
2021
box-shadow: var(--shadow-floating-legacy, var(--color-shadow-large)) !important;
2122

2223
/* Carets */
@@ -54,150 +55,180 @@
5455
}
5556
}
5657

58+
/* The caret variants below are authored as expanded per-class selectors
59+
** (rather than nesting `&::before`/`&::after` under a selector list) so each
60+
** rule's subject buckets by its own class during style recalc. The merged
61+
** `:is(.Popover-message--…, …)::before` form cannot be fast-rejected by Blink
62+
** and shows up as pure slow-path selector matching. */
63+
5764
/* Bottom-oriented carets */
58-
.Popover-message--bottom,
59-
.Popover-message--bottom-right,
60-
.Popover-message--bottom-left {
61-
&::before,
62-
&::after {
63-
top: auto;
64-
border-bottom-color: transparent;
65-
}
65+
.Popover-message--bottom::before,
66+
.Popover-message--bottom::after,
67+
.Popover-message--bottom-right::before,
68+
.Popover-message--bottom-right::after,
69+
.Popover-message--bottom-left::before,
70+
.Popover-message--bottom-left::after {
71+
top: auto;
72+
border-bottom-color: transparent;
73+
}
6674

67-
&::before {
68-
bottom: -16px;
69-
border-top-color: var(--borderColor-default);
70-
}
75+
.Popover-message--bottom::before,
76+
.Popover-message--bottom-right::before,
77+
.Popover-message--bottom-left::before {
78+
bottom: -16px;
79+
border-top-color: var(--borderColor-default);
80+
}
7181

72-
&::after {
73-
bottom: -14px;
74-
/* stylelint-disable-next-line primer/colors */
75-
border-top-color: var(--overlay-bgColor);
76-
}
82+
.Popover-message--bottom::after,
83+
.Popover-message--bottom-right::after,
84+
.Popover-message--bottom-left::after {
85+
bottom: -14px;
86+
/* stylelint-disable-next-line primer/colors */
87+
border-top-color: var(--overlay-bgColor);
7788
}
7889

7990
/* Top and Bottom: Right-oriented carets */
8091
.Popover-message--top-right,
8192
.Popover-message--bottom-right {
8293
right: -9px;
8394
margin-right: 0;
95+
}
8496

85-
&::before,
86-
&::after {
87-
left: auto;
88-
margin-left: 0;
89-
}
97+
.Popover-message--top-right::before,
98+
.Popover-message--top-right::after,
99+
.Popover-message--bottom-right::before,
100+
.Popover-message--bottom-right::after {
101+
left: auto;
102+
margin-left: 0;
103+
}
90104

91-
&::before {
92-
right: var(--base-size-20);
93-
}
105+
.Popover-message--top-right::before,
106+
.Popover-message--bottom-right::before {
107+
right: var(--base-size-20);
108+
}
94109

95-
&::after {
96-
right: var(--base-size-20);
97-
margin-right: 1px;
98-
}
110+
.Popover-message--top-right::after,
111+
.Popover-message--bottom-right::after {
112+
right: var(--base-size-20);
113+
margin-right: 1px;
99114
}
100115

101116
/* Top and Bottom: Left-oriented carets */
102117
.Popover-message--top-left,
103118
.Popover-message--bottom-left {
104119
left: -9px;
105120
margin-left: 0;
121+
}
106122

107-
&::before,
108-
&::after {
109-
left: var(--base-size-24);
110-
margin-left: 0;
111-
}
123+
.Popover-message--top-left::before,
124+
.Popover-message--top-left::after,
125+
.Popover-message--bottom-left::before,
126+
.Popover-message--bottom-left::after {
127+
left: var(--base-size-24);
128+
margin-left: 0;
129+
}
112130

113-
&::after {
114-
left: var(--base-size-24);
115-
margin-left: 1px;
116-
}
131+
.Popover-message--top-left::after,
132+
.Popover-message--bottom-left::after {
133+
left: var(--base-size-24);
134+
margin-left: 1px;
117135
}
118136

119137
/* Right- and Left-oriented carets */
120-
.Popover-message--right,
121-
.Popover-message--right-top,
122-
.Popover-message--right-bottom,
123-
.Popover-message--left,
124-
.Popover-message--left-top,
125-
.Popover-message--left-bottom {
126-
&::before,
127-
&::after {
128-
top: 50%;
129-
left: auto;
130-
margin-left: 0;
131-
border-bottom-color: transparent;
132-
}
138+
.Popover-message--right::before,
139+
.Popover-message--right::after,
140+
.Popover-message--right-top::before,
141+
.Popover-message--right-top::after,
142+
.Popover-message--right-bottom::before,
143+
.Popover-message--right-bottom::after,
144+
.Popover-message--left::before,
145+
.Popover-message--left::after,
146+
.Popover-message--left-top::before,
147+
.Popover-message--left-top::after,
148+
.Popover-message--left-bottom::before,
149+
.Popover-message--left-bottom::after {
150+
top: 50%;
151+
left: auto;
152+
margin-left: 0;
153+
border-bottom-color: transparent;
154+
}
133155

134-
&::before {
135-
margin-top: -9px;
136-
}
156+
.Popover-message--right::before,
157+
.Popover-message--right-top::before,
158+
.Popover-message--right-bottom::before,
159+
.Popover-message--left::before,
160+
.Popover-message--left-top::before,
161+
.Popover-message--left-bottom::before {
162+
margin-top: -9px;
163+
}
137164

138-
&::after {
139-
margin-top: -8px;
140-
}
165+
.Popover-message--right::after,
166+
.Popover-message--right-top::after,
167+
.Popover-message--right-bottom::after,
168+
.Popover-message--left::after,
169+
.Popover-message--left-top::after,
170+
.Popover-message--left-bottom::after {
171+
margin-top: -8px;
141172
}
142173

143174
/* Right-oriented carets */
144-
.Popover-message--right,
145-
.Popover-message--right-top,
146-
.Popover-message--right-bottom {
147-
&::before {
148-
right: -16px;
149-
border-left-color: var(--borderColor-default);
150-
}
175+
.Popover-message--right::before,
176+
.Popover-message--right-top::before,
177+
.Popover-message--right-bottom::before {
178+
right: -16px;
179+
border-left-color: var(--borderColor-default);
180+
}
151181

152-
&::after {
153-
right: -14px;
154-
/* stylelint-disable-next-line primer/colors */
155-
border-left-color: var(--overlay-bgColor);
156-
}
182+
.Popover-message--right::after,
183+
.Popover-message--right-top::after,
184+
.Popover-message--right-bottom::after {
185+
right: -14px;
186+
/* stylelint-disable-next-line primer/colors */
187+
border-left-color: var(--overlay-bgColor);
157188
}
158189

159190
/* Left-oriented carets */
160-
.Popover-message--left,
161-
.Popover-message--left-top,
162-
.Popover-message--left-bottom {
163-
&::before {
164-
left: -16px;
165-
border-right-color: var(--borderColor-default);
166-
}
191+
.Popover-message--left::before,
192+
.Popover-message--left-top::before,
193+
.Popover-message--left-bottom::before {
194+
left: -16px;
195+
border-right-color: var(--borderColor-default);
196+
}
167197

168-
&::after {
169-
left: -14px;
170-
margin-bottom: 1px;
171-
/* stylelint-disable-next-line primer/colors */
172-
border-right-color: var(--overlay-bgColor);
173-
}
198+
.Popover-message--left::after,
199+
.Popover-message--left-top::after,
200+
.Popover-message--left-bottom::after {
201+
left: -14px;
202+
margin-bottom: 1px;
203+
/* stylelint-disable-next-line primer/colors */
204+
border-right-color: var(--overlay-bgColor);
174205
}
175206

176207
/* Right and Left: Top-oriented carets */
177-
.Popover-message--right-top,
178-
.Popover-message--left-top {
179-
&::before,
180-
&::after {
181-
top: var(--base-size-24);
182-
}
208+
.Popover-message--right-top::before,
209+
.Popover-message--right-top::after,
210+
.Popover-message--left-top::before,
211+
.Popover-message--left-top::after {
212+
top: var(--base-size-24);
183213
}
184214

185215
/* Right and Left: Bottom-oriented carets */
186-
.Popover-message--right-bottom,
187-
.Popover-message--left-bottom {
188-
&::before,
189-
&::after {
190-
top: auto;
191-
}
216+
.Popover-message--right-bottom::before,
217+
.Popover-message--right-bottom::after,
218+
.Popover-message--left-bottom::before,
219+
.Popover-message--left-bottom::after {
220+
top: auto;
221+
}
192222

193-
&::before {
194-
bottom: var(--base-size-16);
195-
}
223+
.Popover-message--right-bottom::before,
224+
.Popover-message--left-bottom::before {
225+
bottom: var(--base-size-16);
226+
}
196227

197-
&::after {
198-
bottom: var(--base-size-16);
199-
margin-bottom: 1px;
200-
}
228+
.Popover-message--right-bottom::after,
229+
.Popover-message--left-bottom::after {
230+
bottom: var(--base-size-16);
231+
margin-bottom: 1px;
201232
}
202233

203234
@media (min-width: 544px) {

0 commit comments

Comments
 (0)