通过 :has 查找对应选择器的祖先或父级元素
:has
是 CSS 中唯一可以实现“向上”选择(选择祖先或父级元素)的伪类选择器。以下是几个经典的应用场景和示例,展示其强大功能:
1. 匹配祖先元素
场景:
选择包含特定子元素的父级或祖先元素。
示例:
<div class="card">
<p>普通内容</p>
</div>
<div class="card">
<p class="highlight">重要内容</p>
</div>
/* 选择包含 .highlight 的所有 .card */
.card:has(.highlight) {
border: 2px solid red;
}
结果:
- 第二个
.card
会被选中,因为它包含了.highlight
。
2. 基于子元素的状态修改父级样式
场景:
当表单的输入框被聚焦时,为其父容器添加样式。
示例:
<div class="form-group">
<label for="input1">Name</label>
<input type="text" id="input1">
</div>
<div class="form-group">
<label for="input2">Email</label>
<input type="email" id="input2">
</div>
/* 当 input 获得焦点时,修改其父级 .form-group 的样式 */
.form-group:has(input:focus) {
background-color: #f0f8ff;
}
结果:
- 当任意输入框被聚焦时,其所在的
.form-group
会改变背景颜色。
3. 选择嵌套结构中的祖先元素
场景:
为包含激活状态链接的导航菜单项添加样式。
示例:
<ul class="menu">
<li><a href="#home">Home</a></li>
<li class="menu-item">
<a href="#about" class="active">About</a>
</li>
<li><a href="#contact">Contact</a></li>
</ul>
/* 选择包含激活状态链接的 .menu-item */
.menu-item:has(a.active) {
font-weight: bold;
}
结果:
- 第二个
.menu-item
会加粗,因为它包含了一个.active
链接。
4. 条件选择:基于复杂嵌套结构的样式
场景:
选中特定的嵌套结构中的祖先或容器。
示例:
<section class="articles">
<article>
<h2>Post 1</h2>
<p>Summary of the post...</p>
</article>
<article>
<h2>Post 2</h2>
<p class="featured">This is a featured post...</p>
</article>
</section>
/* 选择包含 .featured 段落的 article 元素 */
.article:has(.featured) {
background-color: #ffe4e1;
}
结果:
- 第二个
<article>
的背景颜色会改变。
5. 基于特定后代的显示控制
场景:
隐藏不包含指定元素的父级。
示例:
<div class="container">
<p>Text 1</p>
</div>
<div class="container">
<p class="highlight">Text 2</p>
</div>
/* 隐藏不包含 .highlight 的 .container */
.container:not(:has(.highlight)) {
display: none;
}
结果:
- 第一个
.container
会被隐藏,因为它不包含.highlight
。
6. 组合多个选择器
场景:
复杂逻辑选择器,用于满足多个条件。
示例:
<div class="product">
<h3>Product A</h3>
<span class="stock out">Out of Stock</span>
</div>
<div class="product">
<h3>Product B</h3>
<span class="stock in">In Stock</span>
</div>
/* 选择含有 "Out of Stock" 的产品,并修改其样式 */
.product:has(.stock.out) {
opacity: 0.5;
}
结果:
- 第一个
.product
的透明度会降低,因为它包含了span.stock.out
。
7. 兄弟节点与父级结合使用
场景:
基于兄弟元素的存在改变祖先样式。
示例:
<div class="panel">
<h1>Title</h1>
<h2>Subtitle</h2>
</div>
<div class="panel">
<h1>Title</h1>
</div>
/* 选择包含 h1 后有 h2 的 .panel */
.panel:has(h1 + h2) {
border: 2px solid green;
}
结果:
- 第一个
.panel
会加边框,因为它包含了h1
后面紧邻的h2
。
总结
:has
在复杂的嵌套结构中可以极大地增强 CSS 的选择能力,尤其是在需要“向上”选择或基于某些条件动态修改样式的场景中,非常有用。
#前端开发
分享于 2025-01-11