前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库CSS :is() vs :where() specificity
CSS层叠与选择器

is() 和 where() 在优先级上有什么区别?

两者功能一样,都是把多个选择器合并成一组来匹配。区别在优先级::is() 的优先级等于参数里最高的那个选择器,:where() 的优先级永远是 0。所以 :where() 写的样式特别容易被覆盖,适合做默认值。

前端进阶之旅 · 一题精讲更新于 2026.09.29
CSS#层叠与选择器
先看核心答案读代码示例
理解线索

功能相同,优先级相反

  1. :is()取参数列表中优先级最高的那个选择器的值
  2. :where()不管参数多复杂,自身优先级始终是 0
  3. 容错解析参数里有一个无效选择器不会让整组失效,只跳过那一个

传统写法里 h1, h2, h3 {} 如果其中一个选择器无效,整条规则作废。:is() 和 :where() 不会,它们只跳过无效的那一个。

核心回答

先记住这个答案

:is() 和 :where() 都接受一组选择器作为参数,匹配其中任意一个就算命中。写法和效果完全一样,唯一的区别是优先级。:is(.a, #b) 的优先级按参数中最高的 #b 来算,达到 ID 级别。而 :where(.a, #b) 的优先级始终是 0,随便一个类选择器就能覆盖。

  • :is() 优先级取参数中最高的
  • :where() 优先级永远是 0
  • 两者都能简化重复的选择器嵌套
  • :where() 适合写易覆盖的基础样式

用它们简化选择器嵌套

以前给多层嵌套的元素写样式,经常要把选择器复制好几遍。比如文章里的标题链接,手动列举特别啰嗦。:is() 可以把重复的部分折叠起来。

简化多级嵌套选择器CSS
/* 以前的写法,每个标题都要列出来 */
.article h1 a,
.article h2 a,
.article h3 a { color: inherit; }

/* 用 :is() 简化 */
.article :is(h1, h2, h3) a { color: inherit; }

两种写法选中的元素完全一样。但优先级不同:传统写法里每条的优先级是一个类加一个标签加一个标签,:is() 版本里 :is(h1, h2, h3) 的优先级只取标签级别。 如果参数里混了 ID 选择器,比如 :is(#sidebar, .main),整个 :is() 的优先级就被拉到 ID 级别。哪怕实际命中的是 .main,优先级也按 #sidebar 来算。这一点容易踩坑。

where() 适合写可覆盖的默认样式

做组件库或 CSS reset 时,希望预设的样式尽量容易被业务代码覆盖。:where() 就是为这个场景设计的,因为它的优先级是 0,任何带类名的选择器都能盖过它。

用 where() 写不挡路的 resetCSS
/* reset 样式用 :where(),优先级为 0 */
:where(ul, ol) {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* 业务代码随便一个类就能覆盖 */
.nav-list {
  padding: 16px;
}

如果 reset 用的是 :is(ul, ol) 或者直接写 ul, ol,优先级虽然只有标签级别,但某些情况下还是会和业务样式打架。用 :where() 就完全没有这个问题。Tailwind CSS 的 preflight 就大量使用 :where(),保证用户写的任何工具类都能覆盖 reset 里的样式。

容错解析:一个坏选择器不连累整组

传统选择器列表 h1, h2::xyz, h3 {} 里如果 h2::xyz 不合法,浏览器会把整条规则丢弃,h1 和 h3 也不会生效。

:is() 和 :where() 改进了这一点。:is(h1, h2::xyz, h3) 里 h2::xyz 不合法时,只跳过它,h1 和 h3 照常匹配。这在跨浏览器写样式时很有用,可以把实验性选择器和标准选择器放在一起,旧浏览器自动忽略不认识的那个。

回答前,多想一步

容易答错的地方

以为 is() 的优先级按实际命中的参数算
不是。:is(.a, #b) 无论实际命中的是 .a 还是 #b,优先级都按最高的 #b 来算。这是规范明确规定的,取参数列表中优先级最高的那个。
把 where() 当成 is() 的别名用
功能上确实一样,但优先级天差地别。:where() 的优先级是 0,意味着几乎所有正常写法都能覆盖它。在需要样式有一定强度的场景用了 :where(),很容易被意外覆盖。
试着用自己的话回答

面试官还会怎么问?

is() 能嵌套使用吗?

可以。:is(.card, .panel) :is(h1, h2) 完全合法,匹配 .card 或 .panel 里面的 h1 或 h2。嵌套使用时优先级各自独立计算,外层取外层参数的最高值,内层取内层参数的最高值。

能不能用 is() 匹配伪元素?

不能。:is(::before, ::after) 是不合法的。规范要求 :is() 和 :where() 的参数只能是复合选择器,不能是伪元素。想给多个伪元素写相同样式,还是要分开写。

CSS 原生嵌套和 is() 有什么关系?

CSS 原生嵌套规范里,浏览器在某些情况下会自动把父选择器包裹在 :is() 里。比如 .a { .b & {} } 解析后相当于 .b :is(.a)。所以使用原生嵌套时要注意,:is() 的优先级规则会悄悄参与计算。

从一道题,走向一组知识

把知识连起来

层叠与选择器

没放进 @layer 的样式和层里的样式冲突,谁赢?

:where() 写零优先级样式,@layer 也能控制优先级层级,两者可以搭配使用。

层叠与选择器

@layer 是干什么用的?层的声明顺序怎么影响样式优先级?

理解了 :is() 的优先级提升效果,再看 @layer 怎么在层级维度管理优先级,就能串起来。

参考资料

  • CSS:层叠与选择器参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 用它们简化选择器嵌套
  3. where() 适合写可覆盖的默认样式
  4. 容错解析:一个坏选择器不连累整组
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑