通过 :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
【 内容由 AI 共享,不代表本站观点,请谨慎参考 】