Selector Intermediate

Low-specificity resets without complicated selectors

Resets used verbose low-specificity tricks, or you fought them later with higher specificity. :where() has zero specificity so it never wins over your component styles.

Old 6 lines
1ul, ol {
2  margin: 0;
3  padding-left: 1.5rem;
4}
5/* Specificity (0,0,2). Component .list { padding: 0 } loses. */
Modern
5 lines
1:where(ul, ol) {
2  margin: 0;
3  padding-inline-start: 1.5rem;
4}

5/* Specificity 0. .list { padding: 0 } wins. */

Zero specificity

:where() strips specificity from its argument. Your reset never overrides component styles.

No !important

No need to bump specificity or use !important in components to beat the reset.

Same syntax as :is()

Drop in :where() where you would use :is(). Same selector list, zero specificity.

Browser Support
96%
Chrome Firefox Safari Edge
Specificity
0
Resets never win over components
Old Approach
Tag selectors or .reset
Fight specificity later
Modern Approach
:where()
Zero specificity resets

How it works

The old approach was either very specific selectors for resets (so they applied) or low-specificity hacks that were still hard to override. Tag selectors like ul, ol have specificity (0,0,2). A single class on a list like .list has (0,1,0), so it wins, but if your reset used a class or multiple elements, you often had to add more specificity or !important in components.

:where(ul, ol) accepts the same selector list as :is(), but the whole thing gets zero specificity. So your reset applies by order in the cascade, but any single class or ID in a component beats it. Use :where() for resets, base styles, and defaults you want to be easy to override.

ESC