:where()本身不降低权重,只构造0-0-0新规则;真正起作用的是外层带权选择器,单独使用:where(.btn)因权重为0-0-0无法覆盖UA样式(0-0-1),必须搭配业务专属外层选择器(如.my-app)才能生效。

:where() 本身不降低权重,它只构造一个权重恒为 0-0-0 的新规则;真正起作用的是外层那个带权的选择器。
为什么单独写 :where(.btn) 样式根本不起作用
浏览器看到 :where(.btn) 时,确实会匹配所有带 .btn 的元素,但这条规则的 specificity 是 0-0-0 —— 连 button 元素默认的 UA 样式(通常为 0-0-1)都盖不住。它不是“赢不了”,而是“没资格参赛”。常见错误包括:
- 把第三方类名整个塞进
:where(),比如:where(.ant-btn),结果整条规则变空气 - 误以为
:where()能穿透!important,其实完全无效 - 在样式表里把它写在第三方 CSS 之前,顺序一错,连竞争机会都没有
:where() 必须搭配外层命名空间才可用
真正生效的写法永远是:外层用一个稳定、业务专属、有实际权重的选择器(如主题 class 或语义容器),内层用 :where() 放需要“归零”的目标。例如:
-
.my-app :where(button, input, select)—— 权重来自.my-app(0-1-0),括号内清零但整体有效 -
article :where(h1, h2, h3)—— 利用语义容器提权,避免和全局标题规则冲突 -
form :where([type="text"], [type="email"])—— 属性选择器在:where()内也归零,安全
⚠️ 错误示范::where(.my-app button)(整条 0-0-0)、:where(#main) button(ID 塞进去白费)、:where(.reset-list) ul(外层 class 已经带权,违背归零意图)
立即学习“前端免费学习笔记(深入)”;
哪些内容能放进 :where() 括号里
:where() 括号内支持元素名、类名、属性选择器(如 [disabled])、伪类(如 :hover),但有硬限制:
- 不能含伪元素(
::before),整条规则被静默丢弃 - 不能嵌套
:not()、:is()或另一层:where() - 不支持
:nth-child()等需运行时计算的选择器 - Safari 15.0–15.3 对多选项列表(如
:where(.a, .b, .c))有解析 bug,可能漏掉最后一个,上线前必须实测
最稳妥的用法是纯元素或带属性的选择器,比如 :where(ul, ol, dl) 或 :where([type="checkbox"])。
和 all: unset 搭配时容易踩的坑
:where(*) { all: unset; } 看似彻底,但副作用明显:
- 会切断
inherit链,导致color、font-family回退到 UA 默认值(文字全黑、无字体) -
all: unset清掉<select>的原生下拉箭头、<input type="range">的轨道,损害无障碍体验 - 更推荐分层重置:
:where(h1, h2, h3) { all: unset; font-size: inherit; font-weight: bold; }
真正难的不是语法写对,而是判断哪一层该留权、哪一层该放权——外层没权,里面再清零也没用;外层权太高,又违背“便于覆盖”的初衷。生产环境里,:where() 不是覆盖器,是基线归零工具。


















