margin折叠是CSS盒模型在普通文档流中处理块级元素垂直间距的内置规则,当两个垂直外边距毗邻时按取大、相加或取较大负值规则合并,水平margin永不折叠,padding可稳定控制父子间距。

margin 折叠本质是盒模型垂直方向布局的默认行为
它不是 bug,也不是“意外”,而是 CSS 盒模型在**普通文档流中处理块级元素垂直间距时的内置规则**。W3C 明确规定:当两个垂直外边距(margin-top 和 margin-bottom)在普通流中“毗邻”(即中间没有 border/padding/内容/clear 分隔),它们就会折叠为一个外边距——这直接决定了元素在垂直方向上的实际占位和位置关系。
哪些盒模型状态会触发或阻止 margin 折叠?
折叠只发生在满足特定盒模型条件的场景下,关键看是否处于“普通流中的块级格式化上下文(BFC)”以及是否有分隔物:
- ✅ 触发折叠:父元素
height: auto、无border、无padding、无内容,子元素设margin-top: 40px→ 父元素顶部“被顶起”,因为子元素的margin-top和父元素的margin-top折叠了 - ✅ 阻止折叠:
overflow: hidden、display: inline-block、float: left、position: absolute—— 这些都会创建新 BFC 或脱离普通流,让 margin 不再参与折叠 - ✅ 阻止父子穿透:给父元素加
padding-top: 1px或border-top: 1px solid transparent,哪怕 1 像素,也能物理隔开 margin,彻底阻断折叠
垂直方向计算规则怎么影响实际布局?
折叠后的值不是相加,而是按明确逻辑算出来的——这个结果直接决定元素间真实距离,也是你调样式时“为什么没生效”的根源:
- 两正数(如
margin-bottom: 20px+margin-top: 35px)→ 取大值:35px - 一正一负(如
margin-bottom: 20px+margin-top: -12px)→ 相加:8px - 两负数(如
margin-bottom: -15px+margin-top: -25px)→ 取绝对值更大的负值:-25px -
margin-left/margin-right永远不折叠,水平方向永远按相加逻辑
.a { margin-bottom: 20px; }
.b { margin-top: 35px; }
/* .a 和 .b 实际垂直间距 = 35px,不是 55px */为什么用 padding 而不是 margin 控制父子间距?
因为 margin 在父子间容易穿透,而 padding 是盒模型“内部尺寸”,稳定可控——它属于父元素自身内容区的延伸,不会和子元素的 margin 合并:
立即学习“前端免费学习笔记(深入)”;
- ❌ 错误直觉:给父设
margin-top,再给子设margin-top,以为能叠加出更大间距 → 实际可能全折叠成一个值,甚至把整个父容器顶出视口 - ✅ 正确姿势:父元素用
padding-top定义“内边距空间”,子元素用margin-top: 0或干脆不设 → 间距完全由父的 padding 决定,无歧义、可预测 - ⚠️ 注意:百分比
margin(如margin-top: 5%)仍按包含块**宽度**计算,和高度无关;但padding百分比同样如此——这点常被忽略
盒模型里真正“可靠”的垂直间距控制点只有三个:父元素的 padding、子元素的 margin(只设一个方向)、或者用 gap(Flex/Grid 容器)。其余组合,几乎都绕不开折叠规则——它不是边缘情况,而是垂直布局的底层逻辑。










