:where()实现零权重是因为其内部选择器特异性被强制设为0,无论嵌套class或伪类均不增加权重,适合基类重置;但外层加class、覆盖ua样式、跨shadow dom及滥用all: unset会导致失效。

where伪类为什么能实现零权重
:where() 的特殊性在于:它内部选择器的特异性(specificity)被强制计算为 0。哪怕你写 :where(.btn .primary:hover),整个选择器的权重也还是 0-0-0,不会叠加 class 或伪类带来的 10 分。这和 :is() 不同——:is() 会取内部最高权重项作为整体权重。
所以它天生适合写“不抢权”的基类重置:比如统一清除所有 ul、ol 的默认 margin 和 padding,又不想影响后续业务样式里写的 .nav-list { margin: 0 }。
用 where 写重置时必须避开的写法
常见错误是把业务类名直接塞进 :where(),结果反而破坏了零权重意图:
- ❌ 错误:
:where(.reset-list) ul—— 外层.reset-list是 class,权重 +10,整条规则变成 0-1-0 - ✅ 正确:
:where(ul, ol, dl) { margin: 0; padding: 0; }—— 全是元素选择器,权重稳稳 0-0-0 - ⚠️ 注意:
:where([type="checkbox"])是合法的,属性选择器在:where()内也归零;但:where(div.class)就不行,class 一出现,权重就破防
哪些场景下 where 重置会意外失效
不是所有重置都适合用 :where(),尤其当你要覆盖 UA 样式(浏览器默认样式)时:
- Chrome 对
<input type="search">的内部::-webkit-search-decoration等伪元素有强 UA 规则,:where(input[type="search"]) { ... }无法覆盖它们——因为伪元素不在:where()范围内,且 UA 权重常高于 0-0-0 - Firefox 的
<button></button>默认margin有时靠 UA 的display: inline-block隐式影响布局,单靠:where(button) { margin: 0 }可能清不干净,得配合display: revert或revert-layer - 如果项目还用了 CSS-in-JS 或 Shadow DOM,
:where()无法穿透作用域边界,重置只在当前 scope 生效
和 all: unset 搭配使用的实际效果
:where() 常和 all: unset 组合,但要注意副作用:
-
:where(*) { all: unset; }看似彻底,但会抹掉inherit关键字的自然继承链(比如color、font-family),导致文字变黑、无字体 - 更稳妥的是分层重置:
:where(h1, h2, h3, h4, h5, h6) { all: unset; font-size: inherit; font-weight: bold; } - 对表单控件,
all: unset会让<select></select>失去原生下拉箭头、<input type="range">失去滑块轨道——这些 UI 信号一旦清空,无障碍支持和用户预期都会受损
立即学习“前端免费学习笔记(深入)”;
真正难的不是写出零权重规则,而是判断哪部分样式「值得重置」、哪部分「必须保留」。比如 box-sizing 用 :where(*) 设成 border-box 很安全,但动 cursor 或 outline 就容易踩进可访问性坑里。










