clear: both 的空 div 会引发外边距合并,使上方 margin-top “消失”;因其高度为0且未触发BFC,无法隔离相邻块级元素的 margin collapse。

为什么 clear: both 的空 div 会让上面的 margin-top 消失
因为块级元素在文档流中发生外边距合并(margin collapse),而空的清除浮动元素(比如 <div style="clear:both"></div>)虽然高度为 0,但它仍是一个参与 BFC 的普通块盒——只要它前面有相邻的块级兄弟元素,就可能触发上下外边距合并。此时上方元素的 margin-top 会“穿过”这个空盒子,和它再上一个块的 margin-bottom 合并,看起来就像消失了。
常见错误现象:h2 设了 margin-top: 20px,但紧跟着一个 <div class="clearfix"></div>,结果顶部空白没了;或者两个段落之间加了清除块,段落间距变小甚至归零。
- 空清除块必须有“格式化上下文边界”,否则无法隔离 margin collapse —— 单纯
clear: both不够 - 如果清除块本身没有内容、没有 padding、没有 border、没有 min-height,那它几乎就是透明的 margin 合并通道
- IE6/7 下更混乱:有些情况会创建匿名块、触发 hasLayout,表现不一致
用 overflow: hidden 触发 BFC 是最稳的替代方案
比起插入空标签,直接让浮动容器自己包裹子浮动,同时阻止内部 margin 外溢,是更干净的做法。关键是让父容器形成 BFC(块级格式化上下文),这样内部浮动不会脱离文档流,外部 margin 也不会和子元素合并。
使用场景:浮动布局的卡片列表、侧栏+主内容结构、老项目兼容性要求高但不能改 HTML 结构时。
立即学习“前端免费学习笔记(深入)”;
- 给浮动容器加
overflow: hidden或overflow: auto(注意:overflow: visible不行) - 现代写法可用
display: flow-root—— 专为此设计,无副作用,Chrome 58+/Firefox 53+ 支持 - 避免用
overflow: hidden时意外裁剪内容(比如下拉菜单、阴影溢出) -
display: flow-root性能略优于overflow,且不改变滚动行为或触发合成层
如果非得用清除元素,别让它“空着身子上场”
空清除块的问题根源在于它太“轻”:没有高度、没有边界、没触发 BFC。只要给它一点“存在感”,就能打断 margin collapse 链路。
参数差异:height: 0 还是 font-size: 0?其实都不如加个不可见但有物理占位的属性。
- 加
line-height: 0+font-size: 0可防止某些浏览器生成幽灵空白节点 - 更可靠的是加
min-height: 1px或padding-top: 1px—— 极小但足够阻断 margin 合并 - 不要用
visibility: hidden或opacity: 0,它们不改变盒模型,照样合并 - 避免
position: absolute清除,它完全脱离文档流,无法撑开父容器
现代项目优先用 Flex/Grid,而不是清除浮动
清除浮动本质是修补浮动布局的历史包袱。现在 display: flex 和 display: grid 能天然包裹子项、无需清除、不触发 margin collapse 异常,还支持对齐、顺序、响应式等原生能力。
性能影响:Flex/Grid 容器自动建立独立格式化上下文,子元素 margin 不会与外部合并,也无需 hack。
- 侧栏布局?用
display: flex+flex: 1替代 float + clear - 多列卡片?
display: grid+grid-template-columns更可控 - 兼容性底线是 IE11?Flex 基本可用,Grid 需要降级方案(比如
@supports) - 别为了“清除”去写额外 CSS 类,先问一句:这地方真需要浮动吗?
真正容易被忽略的是:很多所谓“清除问题”,其实是没理清 margin collapse 的触发条件——不是所有 margin 都会合并,只有**相邻的、处于同一 BFC 中的块级盒**才会。一旦你意识到这点,问题就从“怎么清浮动”变成了“怎么划清 BFC 边界”。










