:is()取括号内最高权重选择器的specificity,:where()恒为0-0-0;前者适合增强样式,后者专用于零干扰基底重置。

:is() 和 :where() 的权重计算规则完全不同
这是最核心、最容易踩坑的点——:is() 取括号内**最高 specificity 的选择器**作为整个伪类的权重;而 :where() **始终为 0-0-0**,不参与层叠竞争。
比如::is(.btn, #header, [data-id]) 的权重等同于 #header(即 1-0-0),能轻松覆盖 .btn:hover;但 :where(.btn, #header, [data-id]) 权重是 0-0-0,连一个普通的 div 标签选择器都压不过。
- 误以为
:where()是“更安全的:is()”?实际它是“完全无权的兜底工具” - 用
:is()写重置样式时,可能意外覆盖第三方组件的高权重要求(如 Ant Design 的.ant-btn) -
:where()配合!important也没用——权重为 0 的声明,加!important仍会被任何非 0 权重规则覆盖
:is() 更适合统一控制已有样式的增强逻辑
当你需要给多个不相关选择器加同一组交互态或状态样式(比如 hover、focus、disabled),又不想重复写三遍规则,:is() 是首选。
典型场景::is(header, main, footer) a:hover 替代传统逗号分组,语义清晰、维护成本低,且权重可控。
- 支持嵌套使用:
:is(.card, .modal) :is(h1, h2, .title) - 可出现在选择器任意位置:
.container :is(.btn-primary, .btn-secondary)或:is(.dark, .light) .text - 注意:括号内若混入 ID 选择器(如
:is(.foo, #bar)),整条规则权重升为 1-0-0,可能破坏原有 CSS 层叠预期
:where() 专用于零干扰的基底样式与设计系统重置
它真正的价值不是“简化写法”,而是“不抢权重”。在框架或设计系统中做全局默认样式、CSS Reset、或 scoped style 下的穿透覆盖时,:where() 才是安全解法。
例如重置所有第三方组件的默认 margin::where(*) { margin: 0; } 不会干扰任何已有规则;又或者在 Vue 中穿透匹配::where(.el-button) { padding: 8px 16px; },不会因权重过高导致子组件样式被意外覆盖。
- 和
:is()语法完全一致,替换只需改函数名,但行为天差地别 - 不能靠它“强制覆盖”——想覆盖别人样式?该用更高 specificity,而不是换伪类
- 搭配
@supports做渐进增强更稳妥:@supports selector(:where(*)) { :where(.btn) { border-radius: 4px; } }
兼容性与降级策略必须手动处理
Chrome 105+、Firefox 103+、Safari 15.4+ 支持两者,但 Edge 17 及更早、所有 IE 版本完全不支持。Polyfill(如 css-prefers-color-scheme)对 :is() / :where() 无效,运行时无法模拟权重逻辑。
- 构建时可用 PostCSS 插件(如
postcss-is-pseudo-class)自动转译为逗号分隔的传统写法 - 手写降级需同步处理权重问题:转译后若原用
:is(.a, #b),降级成.a, #b会导致两条规则权重不同,可能引发样式错乱 - 优先用
@supports selector(:is(*))包裹新特性代码,再在外层写兼容 fallback,避免解析失败阻断后续样式
真正难的不是怎么写,而是判断该用哪个——权重是否要参与层叠,决定了你是用 :is() 去“加强控制”,还是用 :where() 去“悄悄收场”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











