:is()和:where()核心差异在于权重::is()取括号内最高权重(如:is(.btn, #header)为1-0-0),适合需保留权重的合并场景;:where()恒为0-0-0,专用于零干扰重置,不可被!important破局,且两者均只做静态匹配、不支持伪元素或动态逻辑。

:is() 和 :where() 看起来只是函数名不同,但实际行为差异极大——选错一个,样式就可能完全失效或意外覆盖。
权重计算规则完全不同
这是最核心、最容易踩坑的点,直接决定样式是否生效、是否被覆盖。
-
:is(.btn, #header)的权重等同于#header(1-0-0),能压过大多数类名选择器;写成:is(.a, .b, .c)则和单个.a权重一样(0-0-1),毫无提权意义 -
:where(.btn, #header)的权重恒为 0-0-0,哪怕里面塞了#nav ul li a:hover,整条规则也只靠外部选择器撑权重(比如nav :where(a)靠nav提供元素权重) - 误用
:where()写覆盖逻辑,结果样式不生效?大概率是它权重为 0,被一个普通的div.link都压过了
什么时候该用 :is()
当你需要统一增强已有样式的交互态、状态或上下文,并且希望保持可控的权重。
- 典型场景:
.button:is(:hover, :focus, :active)替代三行重复规则,语义清晰,权重由.button主导,不会意外提权 - 合并重复祖先路径:
.card :is(h1, p, .meta)比.card h1, .card p, .card .meta更易维护,改.card类名只需动一处 - 避免错误写法:
:is(.card h1, .card p)—— 失去“父级统一”语义,后续改类名反而更难;也不支持伪元素(如.a::before)或孤立伪类(如单独:hover) - Safari ≤15.3 会静默丢弃整条规则,建议用
@supports selector(:is(*))包裹降级规则
什么时候必须用 :where()
当你想“写样式但不抢权”,尤其是做基底重置、设计系统兜底、或 scoped style 下穿透匹配。
- 安全重置默认样式:
:where(*) { margin: 0; }不会干扰任何现有规则;在 Vue<style scoped></style>中写:where(.el-button) { padding: 8px; }也不会因权重过高破坏子组件 - 避免覆盖用户自定义状态:
:where(button, [role="button"]) { cursor: default; }不会压过button:hover { cursor: pointer; } - 不能靠
!important补救——权重为 0 的声明加!important,仍会被任何非 0 权重规则覆盖 - Safari 15.0–15.3 存在解析 bug,可能跳过整条规则;上线前务必实测目标环境
混用时最常被忽略的匹配逻辑
:where(.dark) :is(h1, h2) 不代表“仅在暗色模式下生效”。只要页面 DOM 中存在任意一个带 .dark 类的元素,就会匹配所有 h1 和 h2 —— 它不做条件判断,只做静态匹配。
- 调试时发现白天也触发样式?问题不在浏览器,而在你把
:where()当成了 JS 的if - 真要实现暗色模式逻辑,得用
@media (prefers-color-scheme: dark)或配合属性选择器::is([data-theme="dark"]) h1 - 两者都不支持动态参数、JS 变量或嵌套另一个
:is()/:where();语法稍错(如多逗号、括号未闭合)会导致整条规则被浏览器丢弃,控制台警告可能很模糊
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











