相邻兄弟选择器

学习

相邻兄弟选择器

2026-02-23/0/ 编辑


相邻兄弟选择器

概述

相邻兄弟选择器(Adjacent Sibling Combinator)用于选择紧接在某个元素之后的第一个同级兄弟元素。

语法

元素1 + 元素2 {
  属性: 值;
}

注意: 两个元素之间用加号 + 分隔,并且要有空格。

基本示例

1. 基本用法

/* 选择紧跟在 h2 之后的第一个段落 */
h2 + p {
  color: red;
  font-weight: bold;
}
<h2>标题</h2>
<p>这个段落会被选中(红色粗体)</p>
<p>这个段落不会被选中</p>
<h2>另一个标题</h2>
<p>这个段落会被选中(红色粗体)</p>

2. 选择器类型不限

/* 选择紧跟在 p 之后的第一个 div */
p + div {
  background-color: yellow;
}

/* 选择紧跟在 li 之后的第一个 li */
li + li {
  border-top: 1px solid #ccc;
}

工作原理

相邻兄弟选择器的要求:

  1. 同级关系: 两个元素必须有相同的父元素
  2. 相邻位置: 元素2必须紧接在元素1之后
  3. 只选择一个: 只选择第一个符合条件的元素

图示

父元素
├── 元素1 (p)
├── 元素2 (p) ✓ 会被选中
├── 元素3 (div) ✗ 不会被选中(不是 p)
├── 元素4 (p) ✗ 不会被选中(不是第一个)
└── 元素5 (p) ✗ 不会被选中(不是第一个)

与通用兄弟选择器的区别

相邻兄弟选择器(+)

h2 + p {
  /* 只选择紧跟在 h2 之后的第一个 p */
  color: red;
}

效果: 只选择紧邻的第一个元素

通用兄弟选择器(~)

h2 ~ p {
  /* 选择 h2 之后的所有同级 p 元素 */
  color: red;
}

效果: 选择后面所有的同级元素

对比示例

/* 相邻兄弟选择器 */
.title + p {
  color: red; /* 只有紧邻的第一个 p 是红色 */
}

/* 通用兄弟选择器 */
.title ~ p {
  color: blue; /* title 后面所有的 p 都是蓝色 */
}
<div class="title">标题</div>
<p>第一个段落 - 红色(+) / 蓝色(~)</p>
<p>第二个段落 - 不变色(+) / 蓝色(~)</p>
<div>其他内容</div>
<p>第三个段落 - 不变色(+) / 蓝色(~)</p>

权重计算

相邻兄弟选择器的权重是各组成部分权重之和:

h2 + p {
  /* 权重 = 1(h2) + 1(p) = 2 */
  color: red;
}

.title + .box {
  /* 权重 = 10(.title) + 10(.box) = 20 */
  color: blue;
}

#header + p {
  /* 权重 = 100(#header) + 1(p) = 101 */
  color: green;
}

常见应用场景

1. 列表项分隔线

/* 给列表项添加上边框 */
li + li {
  border-top: 1px solid #eee;
}
<ul>
  <li>列表项 1 (无上边框)</li>
  <li>列表项 2 (有上边框)</li>
  <li>列表项 3 (有上边框)</li>
  <li>列表项 4 (有上边框)</li>
</ul>

2. 表单控件

/* 输入框与标签的间距 */
label + input {
  margin-left: 10px;
}

/* 表单组之间的间距 */
.form-group + .form-group {
  margin-top: 15px;
}
<form>
  <div class="form-group">
    <label>用户名:</label>
    <input type="text">
  </div>
  <div class="form-group">
    <label>密码:</label>
    <input type="password">
  </div>
  <div class="form-group">
    <label>邮箱:</label>
    <input type="email">
  </div>
</form>

3. 标题和段落

/* 标题后的第一个段落特殊样式 */
h2 + p {
  font-size: 18px;
  color: #666;
  margin-top: 10px;
}
<h2>文章标题</h2>
<p>这是摘要段落,会应用特殊样式</p>
<p>这是正文段落,不会应用特殊样式</p>

4. 按钮组

/* 按钮之间的间距 */
.btn + .btn {
  margin-left: 10px;
}
<div>
  <button class="btn">取消</button>
  <button class="btn">确定</button>
  <button class="btn">提交</button>
</div>

5. 布局分隔

/* 段落与标题的间距 */
p + h3 {
  margin-top: 30px;
}

/* 图片与段落的间距 */
img + p {
  margin-top: 15px;
}

6. 卡片布局

/* 卡片之间的间距 */
.card + .card {
  margin-top: 20px;
}

7. 表格行样式

/* 表格行的分隔 */
tr + tr td {
  border-top: 1px solid #ddd;
}

8. 导航菜单

/* 导航项的分隔符 */
.nav-item + .nav-item::before {
  content: "|";
  margin: 0 10px;
  color: #ccc;
}
<nav>
  <a href="#" class="nav-item">首页</a>
  <a href="#" class="nav-item">产品</a>
  <a href="#" class="nav-item">关于</a>
  <a href="#" class="nav-item">联系</a>
</nav>

9. 图标和文字

/* 图标后的文字间距 */
.icon + span {
  margin-left: 8px;
}

/* 图标与链接的间距 */
.icon + a {
  margin-left: 10px;
}

10. 图片库

/* 图片之间的间距 */
.gallery img + img {
  margin-left: 10px;
}

高级用法

1. 与伪类配合

/* 选中第一个元素之外的所有元素 */
li:first-child ~ li {
  /* ... */
}

/* 等同于 */
li + li {
  /* ... */
}

2. 与伪元素配合

/* 在相邻元素前添加内容 */
h2 + p::before {
  content: "→ ";
  color: #3498db;
}

3. 多个相邻选择器组合

/* 链式选择 */
h2 + p + p {
  color: red; /* 选择第二个段落 */
}

/* 等价于 */
h2 + p + p,
h2 + p + p + p,
h2 + p + p + p + p {
  /* 选择第三个及之后的段落 */
}

4. 选择特定状态

/* 选中特定元素之后的元素 */
.active + li {
  background-color: #f9f9f9;
}
<ul>
  <li class="active">当前项</li>
  <li>下一项(会应用背景色)</li>
  <li>再下一项(不会应用背景色)</li>
</ul>

5. 响应式设计

/* 小屏幕下调整间距 */
@media (max-width: 768px) {
  .btn + .btn {
    margin-left: 5px;
    margin-top: 5px;
  }
}

6. 交互动画

/* 悬停效果 */
.box:hover + .next {
  opacity: 0.5;
  transition: opacity 0.3s ease;
}

实战案例

案例1: 评论列表

/* 评论分隔线 */
.comment + .comment {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #eee;
}

/* 评论和回复之间的间距 */
.comment > .replies + .reply {
  margin-top: 10px;
}
<div class="comment-list">
  <div class="comment">
    <p>第一条评论</p>
  </div>
  <div class="comment">
    <p>第二条评论</p>
  </div>
  <div class="comment">
    <p>第三条评论</p>
  </div>
</div>

案例2: 新闻列表

/* 新闻项 */
.news-item {
  padding: 20px;
  border-bottom: 1px solid #eee;
}

/* 第一个新闻项没有上边框 */
.news-item + .news-item {
  border-top: none;
}

/* 标题和摘要的间距 */
.news-item h3 + p {
  margin-top: 10px;
  color: #666;
}
<div class="news-list">
  <div class="news-item">
    <h3>新闻标题1</h3>
    <p>新闻摘要...</p>
  </div>
  <div class="news-item">
    <h3>新闻标题2</h3>
    <p>新闻摘要...</p>
  </div>
</div>

案例3: 步骤指示器

/* 步骤指示器 */
.step {
  display: inline-block;
  width: 40px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border: 2px solid #ddd;
  border-radius: 50%;
}

.step + .step::before {
  content: "→";
  margin: 0 10px;
  color: #ddd;
}
<div class="steps">
  <div class="step">1</div>
  <div class="step">2</div>
  <div class="step">3</div>
  <div class="step">4</div>
</div>

案例4: 价格表

/* 价格表项 */
.price-item {
  display: flex;
  justify-content: space-between;
  padding: 15px 20px;
}

.price-item + .price-item {
  border-top: 1px dashed #eee;
}

案例5: 对话框

/* 消息气泡 */
.message {
  max-width: 70%;
  padding: 10px 15px;
  border-radius: 10px;
  margin-bottom: 10px;
}

.message.sent {
  background: #3498db;
  color: white;
  margin-left: auto;
}

.message.received + .message.received {
  border-bottom-left-radius: 5px;
}

.message.sent + .message.sent {
  border-bottom-right-radius: 5px;
}

注意事项

1. 必须是同级元素

/* ❌ 不会选中 - 不是同级 */
.parent > .first + .second {
  /* ... */
}
<div class="parent">
  <div class="first"></div>
  <div class="wrapper">
    <div class="second"></div>
  </div>
</div>

2. 必须相邻

div + span {
  /* 只选择紧邻的 span */
}
<div>元素1</div>
<span>会被选中</span>
<div>元素2</div>
<span>不会被选中</span>

3. 只选择一个

p + p {
  /* 只选择第一个相邻的 p */
}
<p>段落1</p>
<p>会被选中</p>
<p>不会被选中</p>
<p>不会被选中</p>

4. 空格很重要

/* ❌ 错误: 缺少空格 */
div+p {}

/* ✅ 正确: 有空格 */
div + p {}

5. 与后代选择器的区别

/* 相邻兄弟选择器 - 同级 */
h2 + p {
  /* ... */
}

/* 后代选择器 - 父子 */
div h2 + p {
  /* ... */
}

性能考虑

相邻兄弟选择器的性能通常较好,因为:

  • 只检查相邻的元素
  • 不需要遍历所有后代

但在大量元素的情况下,仍需谨慎使用。

最佳实践

  1. 列表分隔: 使用相邻兄弟选择器添加分隔线
  2. 表单布局: 控制表单元素之间的间距
  3. 按钮组: 管理按钮之间的间距
  4. 导航菜单: 添加分隔符
  5. 布局间距: 控制元素之间的间距
  6. 避免过度使用: 只在确实需要相邻关系时使用
  7. 考虑可读性: 复杂选择器要添加注释

总结

相邻兄弟选择器是一种精确的选择器,能够选择紧接在某个元素之后的第一个同级元素。理解其工作原理和应用场景,能够帮助我们在特定情况下编写更简洁、高效的 CSS 代码。