这是CSS规范定义的垂直外边距合并行为:相邻块级元素在垂直方向直接接触时,上下外边距取较大值而非相加;可用display:flow-root、加border/padding或gap解决。

为什么相邻块级元素的 margin-top 和 margin-bottom 会“消失”一个
这不是 bug,是 CSS 规范明确定义的垂直外边距合并(margin collapse)行为:当两个普通流中的块级元素在垂直方向上“直接接触”时,它们的上下外边距不会相加,而是合并为单个间距,取其中较大值(均为正值时)。比如 .box1 { margin-bottom: 20px; } 紧跟 .box2 { margin-top: 30px; },实际间距只有 30px,不是 50px。
关键触发条件有三个:块级元素、普通文档流、垂直相邻(中间不能有 border/padding/content 隔开)。水平方向的 margin 永远不合并,这点不用操心。
用 display: flow-root 隔离最干净
这是现代项目首选方案——给父容器设 display: flow-root,它会创建一个新的 BFC,天然阻断子元素之间的 margin 合并,且无副作用(不像 overflow: hidden 可能裁剪定位元素或阴影)。
- 适用于兄弟元素合并场景:把它们包进一个
div,然后给这个div加display: flow-root - 也适用于父子塌陷:父元素设
display: flow-root,子元素的margin-top就不会再“冒”到父容器外边去 - 兼容性足够好:Chrome 64+、Firefox 58+、Safari 15.4+、Edge 79+ 均支持;旧版本可降级为
overflow: hidden
加 border 或 padding 是最快捷的“物理隔离”
只要在可能合并的两个 margin 之间插入任何非空的“分隔层”,合并就失效。哪怕只是 1px solid transparent 的边框,或 0.01px 的内边距,浏览器就认为“接触被打破”。
立即学习“前端免费学习笔记(深入)”;
- 对兄弟元素:给上面那个元素加
border-bottom: 1px solid transparent,或下面那个加border-top - 对父子塌陷:给父元素加
padding-top: 0.1px(比1px更轻量,视觉无感) - 注意:
padding: 0或border: none不起作用,必须是计算后大于 0 的值
用 gap 替代 margin 是布局层面的重构思路
如果你本意就是控制一组元素之间的等距分隔,gap 才是语义正确、行为可控的工具——它专为容器内子项间距设计,完全绕过 margin 合并逻辑。
- 仅适用于 Flex 或 Grid 容器:
display: flex; gap: 20px;或display: grid; gap: 20px; -
gap值恒定生效,不受子元素自身margin影响,也不会和父容器发生塌陷 - 慎用于已有复杂定位/浮动的旧结构,改用
gap意味着你主动放弃普通流布局语义
真正容易被忽略的是:margin 合并只发生在「普通流中」。一旦元素脱离(float/position: absolute/display: inline-block),它就不再参与任何合并——但这也意味着你放弃了流式布局的自动适应能力。所以别为了“消灭 margin 合并”而滥用脱离文档流,优先选 flow-root 或 gap 这类不破坏布局意图的解法。


















