CSS :has() 伪类是一个强大的选择器,它允许你根据其子元素、兄弟元素或后代元素的存在与否来选择元素。这个伪类在 CSS 中引入了一种新的方式来实现所谓的“父选择器”功能——即可以根据子元素的状态选择父元素。尽管长期以来开发者们一直希望有一种方法可以在 CSS 中直接选择父元素,但直到 :has() 的出现,才真正实现了这一需求。
语法
:has() 伪类的语法如下:
selector:has(relative-selector) { ... }
selector 是你想要应用样式的元素的选择器。relative-selector 是相对于 selector 内部的一个选择器,可以是子元素、兄弟元素等。
使用示例
根据子元素选择父元素
假设你想当一个列表项(<li>)包含一个特定的链接时改变它的样式,你可以这样做:
<ul>
<li><a href="https://example.com">Example</a></li>
<li>Just text</li>
</ul>
li:has(a) {
background-color: yellow;
}
在这个例子中,只有包含 <a> 链接的 <li> 元素会被应用背景颜色。
根据兄弟元素选择元素
:has() 也可以用来选择基于兄弟元素存在的元素。例如,如果你想选择紧接在标题之后的段落,并且该段落前面有一个特定类名的标题,你可以这样写:
<h2 class="special">Special Title</h2>
<p>This is a paragraph.</p>
<h2>Another Title</h2>
<p>This is another paragraph.</p>
h2.special + p:has(~ .special) {
font-weight: bold;
}
不过,这里的例子可能有点误导,因为 :has() 并不支持选择前一个兄弟元素。实际上,你会使用 h2.special + p 来选择紧跟在 .special 类之后的段落。:has() 更多用于选择自身元素,而不是兄弟元素之间的关系。
嵌套的选择
:has() 可以嵌套使用,这使得它非常灵活。比如,如果你想要选择包含特定类的子元素的父元素,可以这样做:
<div>
<p class="highlight">Highlighted text</p>
</div>
<div>
<p>Normal text</p>
</div>
div:has(>.highlight) {
border: 2px solid blue;
}
在这个例子中,只有包含带有 .highlight 类的 <p> 元素的 <div> 会获得蓝色边框。
浏览器兼容性
截至 2024 年 12 月,:has() 已经被大多数现代浏览器支持,包括 Chrome、Firefox、Safari 和 Edge。然而,总是建议检查最新的 Can I use 数据以获取最准确的浏览器兼容性信息。对于不支持 :has() 的旧版浏览器,你可能需要使用 JavaScript 或者提供回退样式。
注意事项
:has() 不能用于选择 :nth-child、:first-child 等类型的伪类,因为它不是简单地数数,而是依赖于内部选择器的匹配结果。
:has() 的性能可能比其他简单的选择器稍差,因为它需要评估相对选择器,所以在大型文档中应谨慎使用。
由于 :has() 改变了 CSS 选择器的工作原理,它可能会对现有的样式产生意想不到的影响,因此在引入到现有项目时要小心测试。
:has() 为 CSS 提供了更加强大和灵活的选择能力,使开发者能够编写更加简洁和表达力强的样式规则。随着更多浏览器的支持,预计它将在未来的 Web 开发中扮演重要角色。