因为垂直方向margin会折叠,相邻块级元素的上下外边距相遇时只保留较大值,导致间距不可控;用.card + .card { margin-top: 1.5rem; }可精准控制元素间间距,避免首项顶部和末项底部冗余空白。

为什么不用 margin-bottom 统一加间距
因为垂直方向的 margin 会折叠(margin collapsing):两个相邻块级元素的上下外边距相遇时,只保留较大值,导致实际间距不可控。比如给每个 .card 都设 margin-bottom: 1rem,最后一个卡片下方仍会多出 1rem 空白——这不是你想要的“仅元素之间有间距”。
相邻兄弟选择器能绕过这个问题,它只在“有前一个同级兄弟”的前提下才生效,天然排除了首项和末项的干扰。
- 必须确保 HTML 中两个目标元素是同级、且中间无其他标签(哪怕是个空文本节点都可能破坏匹配)
- 不适用于嵌套结构,例如
div + span不会匹配<div><span></span></div>内部的span - IE7+ 支持,现代项目基本无兼容顾虑
.item + .item 是最安全的通用写法
比起依赖语义化标签(如 h2 + p),用类名组合更可控、不易被内容变动破坏。例如一组卡片:
.card { border: 1px solid #eee; padding: 1rem; }
.card + .card { margin-top: 1.5rem; }
这样只有第二个及之后的 .card 才会获得上边距,首张无额外顶部空白,末张也无冗余底部空白。
立即学习“前端免费学习笔记(深入)”;
- 推荐用
margin-top而非margin-bottom,避免父容器内最后一个子项“撑开”底部距离 - 若需适配逻辑方向(如 RTL 或 vertical writing mode),改用
margin-block-start: 1.5rem - 注意:如果中间插入了其他类型元素(如
<hr>或注释节点),.card + .card就会断开,此时得考虑用~或重构结构
遇到隐藏元素或动态渲染时怎么处理
当某个 .card 被 display: none 或 visibility: hidden 时,它在 DOM 中依然存在,但已不参与布局。此时 .card + .card 是否还生效,取决于隐藏方式:
-
display: none→ 元素完全脱离文档流,**不构成兄弟关系**,后面的.card会直接“接续”到上一个可见的.card后面,+仍有效 -
visibility: hidden→ 元素仍在流中占位,+匹配照常,但视觉上间距可能显得突兀 - JS 动态增删节点时,只要插入位置保持紧邻同级,
+无需重写规则,CSS 自动响应
所以真正要小心的是用 opacity: 0 或 transform 移走元素——它们既没消失也没隐藏,只是看不见,+ 依然按原始结构匹配,容易造成意料外的空白。
和 ~ 选择器混用时的边界问题
别误以为 .card ~ .card 是“所有后续卡片”,它其实匹配的是“当前元素之后所有同级 .card”,但它的起点是**每一个**匹配到的左侧元素。也就是说,如果有三个连续 .card,.card ~ .card 会让第二、第三个都命中两次(被第一个和第二个分别选中),导致样式重复叠加。
而 .card + .card 永远只触发一次:只看紧邻的下一个。这是它在间距控制中不可替代的关键——精准、单次、无副作用。
复杂布局里如果需要“跳过中间元素选后续”,说明结构本身可能已偏离语义,这时该优先考虑用 gap(flex/grid)或 JS 控制类名,而不是硬靠选择器兜底。


















