页面上一排卡片,父容器高度是0,背景色完全不显示,子元素全飘到盒子外面去了。新手第一反应是给父元素写个固定高度,结果内容一多就溢出。这就是浮动带来的高度塌陷,clearfix 是专门收拾它的。

塌陷是怎么发生的

元素float之后脱离普通文档流,父元素计算高度时看不见它,于是高度算成0。后面的兄弟元素会顶上来,边框和背景跟着错位。这不是浏览器的bug,规范里就是这么定的,浮动最初是为文字环绕图片设计的。早期有人给父元素加overflow:hidden,确实能撑开,但会裁掉溢出的下拉菜单,还会让position:sticky失效,副作用比问题本身还大。

经典写法每一行都有用

.clearfix::after { content: ''; display: table; clear: both; }

content必须给值,空字符串也行,不给的话伪元素根本不生成,后面两行等于白写。display用table而不是block,是为了避免老浏览器里的margin折叠问题。clear:both把伪元素放到所有浮动元素下方,父元素自然被撑开。IE8以下还要补一句zoom:1触发hasLayout,现在基本可以不管了。

现在更推荐一行搞定

给父元素写display:flow-root,它会建立BFC,既撑开高度又不裁内容,副作用最小。缺点是IE全系不支持,项目还要兼容旧浏览器就老实用伪元素方案。用flex或者grid布局的容器本身不会塌陷,子元素也不再需要清除浮动,新项目优先考虑这两个,代码量少一半。

几个常见的错

  • 只写clear:both不写content:伪元素不生成,整段规则无效。
  • 给浮动元素自己加clearfix:它清的是前面兄弟元素的浮动,管不了自己内部的子元素,位置搞反了。
  • 用br标签清除浮动:能生效,但多出无意义的标签,语义不干净,模板里一多就没法维护。

判断要不要清浮动很简单:父元素的高度是不是该由浮动子元素撑起来。是,就加;父元素本身有明确高度,或者已经是flex容器,加了也是多余代码。