:is()取括号内最高specificity值,:where()权重恒为0-0-0;前者用于需权重压制的场景,后者仅简化写法且不参与层叠竞争。

:is()取括号内最高 specificity,不是加总也不是平均
浏览器对 :is() 的权重计算非常明确:只看括号里所有**合法子选择器**中 specificity 最高的那个,直接拿它的值作为整条规则的权重基准。比如 :is(.btn, #header, [data-id]) 的权重就是 #header 的 1-0-0,哪怕你本意只是想统一匹配按钮。
常见错误现象::is(.a, .b, .c) 和单独写 .a 权重完全一样(都是 0-1-0),没带来任何提升;真正有用的是混用类型,例如 :is(button, [type="submit"], .submit-btn),此时权重由 [type="submit"](0-1-0)或更重的选择器决定。
- 括号内任意一个选择器语法错误(如
:is(.a, , .b)多逗号、:is(.a::before)含伪元素),整条 CSS 规则会被静默丢弃 - 不支持孤立伪类,如
:is(:hover)必须绑定到具体元素(a:hover才合法) - Safari 15.4 之前不支持嵌套,
:is(:is(.a, .b))会直接失效,而非降级
:where()权重恒为 0-0-0,不参与层叠竞争
:where() 的权重逻辑极其简单:无论里面塞了 #nav 还是 div ul li a,整条规则的 specificity 始终是 0-0-0。它不“降权”,而是“无权”——只靠外部选择器“借力”。比如 nav :where(a, button) 的权重只算 nav 那部分(0-1-0)。
典型误用::where(.btn, #primary) { color: red; } 看似想兜底,实际连一个普通 button { color: blue; }(0-0-1)都压不过,因为 0-0-0 天然输给任何非零权重规则。
立即学习“前端免费学习笔记(深入)”;
-
!important对:where()无效:权重为 0 的声明加!important,仍会被任何非 0 权重规则覆盖 - 不能写
:where(a:hover)—— 旧 Safari 可能直接忽略整条规则 - 别在
:where()里塞 ID 或高权重选择器,它不会提升效果,只会制造误解
为什么改个函数名,样式就失效或被覆盖?
根本原因就在权重计算逻辑完全不同::is() 取括号内**最高权重子选择器**参与整体特异性计算,而 :where() 整体权重恒为 0-0-0,不参与层叠竞争。
比如你把 .modal .btn { color: blue; } 改成 .modal :where(.btn) { color: red; },样式大概率不生效——因为后者权重只剩 .modal 的 0-1-0,但若原规则里有更具体的 .modal .btn.primary(0-2-0),它依然能赢;反过来,若改成 .modal :is(.btn, #primary),整条规则权重跳到 1-1-0,可能意外覆盖其他地方的 .btn 样式。
- 想保持低权重、只图写法简洁 → 用
:where() - 需要靠权重压制其他规则 → 才用
:is(),且要确认里面最重的那个选择器确实是你想要的基准 - 二者都不支持动态参数或 JS 变量,纯静态匹配
@supports 检测和兼容性 fallback 必须手动做
:is() 和 :where() 在 Chrome 105+、Firefox 103+、Safari 15.4+ 才稳定支持。Edge 17 及更早、所有 IE 版本完全不支持,且现有 polyfill(如 postcss-preset-env)无法模拟权重逻辑。
安全做法是用 @supports 显式检测:
@supports selector(:is(*)) {
:is(header, main, footer) a:hover { color: green; }
}
@supports selector(:where(*)) {
:where(button, input[type="button"]) { cursor: default; }
}
别指望自动降级;也别在关键路径上全量替换旧写法——先从非核心、低风险场景开始验证,尤其注意 Safari 15.3 及更早版本对嵌套的静默失效行为。


















