父子 margin 合并本质是外边距塌陷,属 CSS 规范行为;最稳妥解法是 display: flow-root 创建无副作用 BFC,兼容现代浏览器;兜底可用 border: 1px solid transparent 或 padding-top: 0.1px。
这不是 bug,而是 CSS 规范定义的行为:当父元素没有 border、padding、inline content 或 BFC 上下文时,子元素的 margin-top 会“穿透”父元素,直接与父元素的 margin(或文档流顶部)合并。结果就是——你设了 margin-top: 20px 给子元素,但父元素整体下移了 20px,子元素在父容器内却像没设 margin 一样紧贴顶部。
display: flow-root
这是专为解决此类问题而生的 display 值,它会创建一个无副作用的 BFC,既不改变布局流,也不影响 overflow 行为,兼容性也足够好(Chrome 64+/Firefox 58+/Safari 15.4+,Edge 79+)。
.parent {
display: flow-root;
}
.child {
m
argin-top: 20px;
}
overflow: hidden 可能意外裁剪内容)overflow: hidden 或 border: 1px solid transparent
只要父元素存在非零的 border 或 padding,就能物理阻断 margin 塌陷。关键是“存在”,不一定要可见。
border-top: 1px solid transparent —— 最常用,兼容所有浏览器
padding-top: 0.1px —— 更轻量,但某些旧版 Safari 对 sub-pixel 渲染不稳定border: 1px solid #fff —— 若父背景是白色,也算“视觉透明”,但不如 transparent 可靠有些方案能止住塌陷,但会带来更隐蔽的问题:
position: absolute 确实让父元素脱离文档流、不再塌陷,但子元素也跟着脱离流,后续布局完全失控float: left 虽然触发 BFC,但会让父元素收缩、可能影响兄弟元素排版,已不推荐用于布局隔离padding-top 替代 margin-top —— 表面可行,但一旦该子元素需要响应式隐藏/显示,padding 就成了“不可撤销的占位”,比 margin 难维护真正关键的不是“怎么让它不塌”,而是“怎么在不破坏布局语义的前提下让它不塌”。flow-root 和 border: 1px solid transparent 是目前平衡性最好的两个选择。