:has()

基线 2023

最新可用

2023年12月起,此功能可在最新的设备和浏览器版本中使用。此功能可能在旧版设备或浏览器中无法使用。

功能性:has() CSS 伪类 表示如果作为参数传递的任何相对选择器与该元素关联时至少匹配一个元素,则表示该元素。此伪类通过采用相对选择器列表作为参数,提供了一种根据参考元素选择父元素或前一个同级元素的方法。

css
/* Selects an h1 heading with a
paragraph element that immediately follows
the h1 and applies the style to h1 */
h1:has(+ p) {
  margin-bottom: 0;
}

:has() 伪类采用其参数中最具体的选择器的特异性,与:is():not() 的方式相同。

语法

css
:has(<relative-selector-list>) {
  /* ... */
}

如果浏览器本身不支持 :has() 伪类,则整个选择器块将失败,除非 :has() 位于宽容的选择器列表中,例如在 :is():where() 中。

:has() 伪类不能嵌套在另一个 :has() 中。这是因为许多伪元素根据其祖先的样式有条件地存在,并且允许 :has() 查询这些元素可能会引入循环查询。

伪元素也不是 :has() 中的有效选择器,并且伪元素不是 :has() 的有效锚点。

示例

使用同级组合符

以下示例中的 :has() 样式声明在 <h1> 标题后立即跟有一个 <h2> 标题时,调整 <h1> 标题后的间距。

HTML

html
<section>
  <article>
    <h1>Morning Times</h1>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
      tempor incididunt ut labore et dolore magna aliqua.
    </p>
  </article>
  <article>
    <h1>Morning Times</h1>
    <h2>Delivering you news every morning</h2>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
      tempor incididunt ut labore et dolore magna aliqua.
    </p>
  </article>
</section>

CSS

css
h1,
h2 {
  margin: 0 0 1rem 0;
}

h1:has(+ h2) {
  margin: 0 0 0.25rem 0;
}

结果

此示例并排显示了两段类似的文本以供比较 - 左侧的文本有一个 H1 标题后跟一个段落,右侧的文本有一个 H1 标题后跟一个 H2 标题,然后是一个段落。在右侧的示例中,:has() 有助于选择紧跟在 H2 元素后的 H1 元素(由下一个同级组合符 + 指示),并且 CSS 规则减少了此类 H1 元素后的间距。如果没有 :has() 伪类,则无法使用 CSS 选择器来选择不同类型的前一个同级元素或父元素。

使用 :is() 伪类

此示例基于之前的示例,演示如何使用:has()选择多个元素。

HTML

html
<section>
  <article>
    <h1>Morning Times</h1>
    <h2>Delivering you news every morning</h2>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
      tempor incididunt ut labore et dolore magna aliqua.
    </p>
  </article>
  <article>
    <h1>Morning Times</h1>
    <h2>Delivering you news every morning</h2>
    <h3>8:00 am</h3>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
      tempor incididunt ut labore et dolore magna aliqua.
    </p>
  </article>
</section>

CSS

css
h1,
h2,
h3 {
  margin: 0 0 1rem 0;
}

:is(h1, h2, h3):has(+ :is(h2, h3, h4)) {
  margin: 0 0 0.25rem 0;
}

结果

这里,第一个:is()伪类用于选择列表中的任何标题元素。第二个:is()伪类用于将下一个兄弟选择器的列表作为参数传递给:has():has()伪类有助于选择任何紧跟(由+指示)H2H3H4元素的H1H2H3元素,并且CSS规则减少了此类H1H2H3元素之后的间距。

此选择器也可以写成

css
:is(h1, h2, h3):has(+ h2, + h3, + h4) {
  margin: 0 0 0.25rem 0;
}

逻辑运算

:has()关系选择器可用于检查多个功能中的一个是否为真或所有功能是否都为真。

通过在:has()关系选择器内使用逗号分隔的值,您可以检查是否存在任何参数。x:has(a, b)将在存在后代ab时设置x的样式。

通过将多个:has()关系选择器链接在一起,您可以检查所有参数是否存在。x:has(a):has(b)将在存在后代ab时设置x的样式。

css
body:has(video, audio) {
  /* styles to apply if the content contains audio OR video */
}
body:has(video):has(audio) {
  /* styles to apply if the content contains both audio AND video */
}

:has() 与正则表达式的类比

有趣的是,我们可以将一些CSS :has()结构与正则表达式中的前瞻断言相关联,因为它们都允许您根据条件选择元素(或正则表达式中的字符串),而无需实际选择与元素(或字符串)本身匹配的条件。

正向前瞻(?=pattern)

在正则表达式abc(?=xyz)中,仅当字符串abc紧跟字符串xyz时才会匹配字符串abc。由于它是一个前瞻操作,因此xyz不包含在匹配项中。

CSS中的类似结构将是.abc:has(+ .xyz):仅当存在下一个兄弟元素.xyz时,它才会选择元素.abc。部分:has(+ .xyz)充当前瞻操作,因为选择了元素.abc而不是元素.xyz

负向前瞻(?!pattern)

类似地,对于负向前瞻情况,在正则表达式abc(?!xyz)中,仅当字符串abc后面xyz时才会匹配字符串abc。类似的CSS结构.abc:has(+ :not(.xyz))如果下一个元素是.xyz,则不会选择元素.abc

规范

规范
选择器级别 4
# 关系型

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅