外边距折叠是css规范规定的块级元素间垂直外边距合并行为,仅发生在普通流中相邻块级盒的margin-top与margin-bottom之间,不适用于行内、浮动、绝对定位及flex/grid子项。

什么是外边距折叠,它只发生在块级元素之间
外边距折叠不是 bug,是 CSS 规范明确规定的布局行为,但只作用于**相邻的块级盒(block-level boxes)在普通流中垂直方向上的 margin-top 和 margin-bottom**。行内元素、浮动元素、绝对定位元素、flex 或 grid 子项都不会触发。
常见误判点:以为父元素和子元素之间“看起来有空隙”就一定是折叠——其实更可能是子元素的 margin-top 传出了父容器(即“外边距塌陷”),本质仍是父子块级盒之间的折叠。
margin 值为 auto 时不会参与折叠
只要任意一个参与比较的外边距值是 auto,折叠立即失效。这在居中布局中很关键:比如用 margin: 0 auto 水平居中块元素,它的左右 margin 不会和兄弟元素折叠,但上下仍可能。
-
margin: 10px auto 20px→ 上下margin仍可折叠,左右不参与 -
display: flex容器里的子项即使设了margin,也不会和兄弟折叠(因为不再是块级流布局) - 使用
gap替代margin是规避折叠最干净的方式(适用于 flex/grid)
父容器没有边框/内边距时,子元素 margin-top 会“穿透”
这是最常被当作“bug”的场景:父元素没设 border、padding 或 overflow,第一个子元素的 margin-top 会直接和父元素的上外边距合并,导致父元素整体下移。
立即学习“前端免费学习笔记(深入)”;
- 修复方式不是给子元素加
padding,而是让父元素“形成 BFC”:overflow: hidden、border: 1px solid transparent、padding: 0.1px都行 -
display: flow-root是语义最清晰的解法,专为此设计,兼容性到 Chrome 64+/Firefox 58+ - 注意:如果父元素本身也有
margin-top,那它会和子元素的margin-top取最大值,而不是相加
空块元素的上下 margin 会完全折叠掉
一个空的 <div></div>,若只有 margin-top: 20px; margin-bottom: 30px,它在渲染时高度为 0,且上下外边距会彼此折叠——最终只保留 30px(较大值),并可能继续和相邻兄弟折叠。
- 这种折叠甚至会跨过多个空块:A(
margin-bottom: 10px)、B(空,margin: 20px 0)、C(margin-top: 5px)→ 实际间距是max(10,20,5) = 20px - 想保留空元素的占位?加
min-height: 0或font-size: 0(避免行盒影响)或干脆用伪元素::before { content: "" } - 调试时用 DevTools 的“Layout”面板看 computed
margin,比肉眼数像素可靠得多
真正麻烦的不是折叠本身,而是它常常隐式发生——你改了一个子元素的 margin,结果三行之外的标题位置变了。这时候得顺着 DOM 往上查,看哪一层没设 border 或 overflow,而不是盯着出问题的元素猛调样式。










