只有需先零权重重置再语义增强时才嵌套:where()于:is()内,如清除标题margin后给卡片内标题加padding;:where()内禁用:is(),否则规则被静默丢弃。

什么时候该用:is()嵌套:where()而不是反过来
只有当你需要「先做零权重重置、再按语义增强」时,才值得嵌套。比如统一清除所有标题的 margin,再单独给卡片里的标题加 padding::where(h1, h2, h3) { margin: 0; } 和 .card :is(h2, h3) { padding: 0.5em 0; } 是两步,不能写成 .card :where(h2, h3) { padding: ... } —— 后者权重为 0,压不过 .card h2 已有的样式。
:is()里能写:where(),但:where()里不能写:is()
这是语法硬限制。浏览器解析时,:where() 内部若出现 :is(),整条规则直接被忽略(不是报错,是静默丢弃)。而 :is() 支持嵌套 :where(),例如::is(.card, :where(header, footer)) h2 是合法的,但实际意义有限——因为 :where() 部分权重归零,整个 :is() 的权重仍由 .card(0-1-0)决定。
-
:is(.a, :where(.b, .c))等价于.a, .b, .c的匹配逻辑,但权重仍是.a的权重 -
:where(.a, :is(.b, .c))❌ 无效,Chrome/Firefox/Safari 全部跳过该规则 - 嵌套层级超过一层(如
:is(:where(.x), :where(.y)))在 Safari 15.3 及更早版本会失效
混合使用时最容易被忽略的性能代价
每个 :where() 都触发一次独立子树遍历,嵌套后不是“一次匹配”,而是多次。比如 article :where(section, aside) :is(h2, h3),浏览器要先找所有 article 下的 section 和 aside,再对每个结果分别查其内部的 h2 和 h3 —— 这比写成 article section h2, article section h3, article aside h2, article aside h3 更慢,且不可缓存。
- 避免在
:where()或:is()内部使用>、+、~关系符,它们不被支持,写了也无效 - 不要为了“看起来短”而嵌套:可读性下降 + 性能变差 + 兼容性风险叠加
- 真实项目中,优先用构建时展开(如 PostCSS 插件),而非运行时嵌套
兼容性兜底必须分层处理,不能靠:where()假装兼容
:where() 在旧浏览器里不会报错,但会被当作非法语法直接忽略——和 :is() 一样。它不是 :is() 的降级替代品,而是语义完全不同的工具。你不能写 :where(.btn, .btn-primary):hover { ... } 来“兼容不支持 :is() 的浏览器”,因为这在 Safari 15.2、360 极速模式下照样失效,且权重为 0 压根覆盖不了已有样式。
立即学习“前端免费学习笔记(深入)”;
- 真正可行的兼容路径只有一条:构建时把
:is()展开为逗号分隔形式,:where()单独保留用于现代环境的零权重场景 - 别在同一个选择器里混用两者来“兼顾”,比如
:is(.a, :where(.b))—— 它既没解决兼容问题,又引入了 Safari 15.3 的解析失败风险 - 最危险的是认为
:where()能绕过权重冲突:它确实权重为 0,但也因此连button { color: blue; }(权重 0-0-1)都压不过
:where() 是真需要零权重,还是只是想“让选择器更短”?后者永远该用构建时展开代替。


















