css selectors has-selector is-selector web-development

现代 CSS 选择器的威力::has, :is 与 :where

掌握新一代 CSS 选择器。了解 :has() 如何作为父级选择器工作,以及 :is() 和 :where() 如何简化您的样式表。

2026-04-18

现代 CSS 选择器的威力::has, :is 与 :where

多年来,CSS 开发者一直梦想着有一个“父级选择器”——一种根据子元素来设置父元素样式的方法。我们也曾深陷于冗长、重复的选择器列表中,这让我们的 CSS 文件变得臃肿。

现代 CSS 终于实现了这些愿望。随着 :has():is():where() 的到来,我们编写选择器的方式发生了根本性的变化。


1. :has():改变游戏规则的“父级选择器”

:has() 伪类可以说是近十年来 CSS 最强大的补充。它允许你根据元素是否包含特定的子元素,或者是否紧跟特定的兄弟元素来选择该元素。

“父级”应用场景

/* 仅当卡片包含图像时才设置卡片样式 */
.card:has(img) {
  display: flex;
  flex-direction: column;
}

/* 仅当卡片包含“精选”标签时才设置样式 */
.card:has(.featured-badge) {
  border: 2px solid gold;
}

“条件”应用场景

你甚至可以根据输入框的状态来设置标签(label)的样式:

/* 如果内部的复选框被勾选,则设置标签样式 */
.form-group:has(input:checked) label {
  color: green;
  font-weight: bold;
}

2. :is():简化复杂的选择器

你是否写过这样的代码?

header h1, header h2, header h3, footer h1, footer h2, footer h3 {
  color: blue;
}

:is() 伪类允许你对选择器进行分组并减少重复:

:is(header, footer) :is(h1, h2, h3) {
  color: blue;
}

核心特性:宽容性

与传统的选择器列表不同,:is()宽容的。如果列表中的一个选择器无效,浏览器会忽略该无效选择器,但仍会对有效的选择器应用样式。


3. :where():零权重的力量

:where() 选择器的工作方式与 :is() 完全相同,但有一个至关重要的区别:它的权重(优先级)始终为零

为什么权重很重要

在 CSS 中,权重最高的选择器获胜。这通常会导致“权重战争”,开发者不得不使用 !important 或长长的选择器链来覆盖样式。

/* 这对权重没有影响 */
:where(.content) p {
  color: gray;
}

/* 一个简单的类选择器现在就可以轻松覆盖它 */
.special-p {
  color: red; /* 获胜,因为 :where() 没有增加任何“重量” */
}

:where() 非常适合 CSS 重置(Resets) 和库作者,他们希望提供易于被用户覆盖的默认样式。


4. 增强型 :nth-childof S

你可能知道 :nth-child(even),但你知道现在可以使用 of 关键字来过滤选择吗?

/* 在所有带有 .visible 类的元素中,选择第 2 个项目 */
li:nth-child(2 of .visible) {
  background: yellow;
}

这对于一些动态列表非常有用,特别是当某些项目通过 display: none 隐藏时。


5. 权重计算器:理解其中的数学逻辑

CSS 权重使用三列进行计算:(A, B, C)

  • A:ID 选择器
  • B:类选择器、属性选择器和伪类
  • C:元素选择器和伪元素

新选择器如何影响计算:

  • :is():has():它们的权重等于其参数列表中权重最高的选择器。
  • :where():权重始终为 (0, 0, 0)

常见问题 FAQ

问::has() 在所有浏览器中都支持吗?

答: 是的!截至 2023 年底,:has() 已在 Chrome、Safari、Firefox 和 Edge 的最新版本中得到支持。在现代 Web 项目中可以放心使用。

问:我应该什么时候使用 :is(),什么时候使用 :where()

答: 当你希望分组的选择器保持其正常权重时,使用 :is()。当你希望样式非常容易被覆盖时(常见于基础样式或重置样式),使用 :where()

问::has() 会影响性能吗?

答: 浏览器对 :has() 进行了显著优化。虽然在单个页面上使用数百次可能会产生微小的影响,但对于大多数 UI 模式来说,它的速度非常快且高效。


编写更简洁、更具声明性的 CSS

通过掌握这些选择器,你可以显著减少 HTML 中的“实用类(utility classes)”数量,并将逻辑保留在它所属的地方:CSS 样式表中。

想看看你的选择器权重如何?试试我们的 CSS 选择器权重计算器(即将推出),掌握 CSS 的数学逻辑。