02浮动

float 诞生时只为做一件事:让文字环绕图片。 前辈们却拿它硬造了十几年的页面布局,留下著名的「高度塌陷」大坑。 本章看懂浮动的本性、踩一遍坑、学会修复,最后记住一句现代口诀:布局交给 Flex/Grid,float 只做文字环绕。

约 16 分钟 6 个动手实验 读懂老代码的钥匙

一、float 的初衷:文字环绕图片

早年报纸排版有个经典需求:图片放左边,文字顺着图片边缘绕着排,而不是整块躲到图片下面。 CSS 为此设计了 float——让元素「浮」起来靠边站,周围的行内内容自动让位环绕。

文字环绕浮动的「图片」:把 float: left 改成 right,图片立刻靠右把文字让到左边
float 的合法取值left(靠左浮)、right(靠右浮)、 none(默认,不浮动)。设置后元素会向指定方向移动,直到碰到容器边缘或另一个浮动元素为止。

二、float 的三个特性

浮动元素有三条「本性」,后面所有的坑都源于它们:

  • ① 脱离文档流:后面的块级盒子当它不存在,会顶上来和它重叠;
  • ② 块级收缩包裹:浮动的块级元素不再撑满父级,宽度收缩到刚好包住内容;
  • ③ 行内内容让位:虽然脱离文档流,但周围的行内内容(文字、行内元素)会绕开它排——这正是环绕效果的来源。
float 三特性:每条都对应一个老 bug
特性具体表现这解释了设么坑
① 脱离文档流后面的块级盒子顶上来与它重叠重叠、错位
② 收缩包裹块级浮动元素不再撑满父级,宽随内容宽度突然变小
③ 行内让位文字 / 行内元素绕开它排图文混排的正常来源
上面看「块级顶上来 + 文字绕行」,下面看「浮动收缩包裹」:把 .ghost 改成 float: right,重叠和绕行立刻换边
记住这条分界线:浮动只对「行内内容」让位,对「块级盒子的位置」完全隐形。 理解了这句,下一节的高度塌陷就好懂了。

三、高度塌陷:浮动最经典的坑

把特性①和②组合起来,就得到浮动时代最著名的 bug:高度塌陷。 父元素不写高度,指望被子元素撑开;可子元素全部浮动了,父元素「看不见」它们—— 于是父元素高度变成 0,边框塌成一条线,后面的兄弟元素整体上移,与浮动的子元素叠在一起。

红色父元素边框塌成一条线:在 .fl-col-parent 上补一行 height: 90px,父级又能包住盒子(但那是硬撑,不是治本)
判断口诀:子级全浮,父级塌陷。只要容器里所有子元素都浮动了,容器高度必然为 0—— 不是浏览器 bug,而是浮动「脱离文档流」这一设计 的必然结果。

四、clear:清除浮动

修复塌陷的第一代方案是 clear 属性。它的含义是: 我这个元素的某一侧不允许出现浮动元素,有的话我就往下挪,直到躲开为止。 在浮动子元素的后面放一个空的块级元素并设置 clear: both,它会被「压」到所有浮动元素的下方, 于是父元素为了包住它,高度就被重新撑开了。

clear 取值行为分析
取值含义什么时候用
none默认,不清除
left左侧不允许有左浮动元素只想躲开左浮动的场景
right右侧不允许有右浮动元素只想躲开右浮动的场景
both左右两侧都不允许有浮动元素无脑选它,最常用
clear: both 修复塌陷:把 .fixclear 改成 none,父级瞬间又塌了——空元素是撑高的关键
clear 只对块级元素生效,且清除的是「它自己」与浮动的关系, 并不会真的把浮动元素拉回文档流——它是绕道,不是根治。

五、clearfix:万能修复方案

空元素方案要污染 HTML,于是前辈们发明了更优雅的clearfix: 用 ::after 伪元素在父元素内容的最末尾「凭空造出」那个带 clear: both 的空盒子。 HTML 一个字都不用改,往父元素身上挂一个 clearfix 类就完事。

clearfix 修复塌陷:把 .fl-clearfix::after 里的 display: table 删掉,看是否还能撑起父级(display: table 是兼容性关键)
现代替代品:display: flow-root(让容器自己形成格式化上下文,天然包住浮动)一行顶 clearfix 三行; 不过既然新项目已经不用浮动做布局,这段代码的主要价值是——看懂老代码

六、历史遗产:float 三栏布局

在 Flex 出现之前,页面骨架就是这么硬凑的:左列左浮动、右列右浮动、中间列用 margin 让位。 注意 HTML 顺序:中间列必须写在最后,这是浮动布局最别扭的约束之一。

float 三栏布局:改 .fl-holy .middlemargin0,中间栏立刻钻到左右两栏下面

这套写法的痛点一眼可见:HTML 顺序与视觉顺序不一致、必须手动清除浮动、 三栏无法天然等高(中间高了,两侧不会跟着长)。 Flex 用三行代码解决了全部问题(display: flex + 两侧定宽 + 中间 flex: 1), 这正是它彻底取代浮动布局的原因,第 05 课详见。

七、本章小结

  • float 的本职工作是文字环绕:left / right / none。
  • 浮动三特性:脱离文档流(块级盒子当它不存在)、收缩包裹(宽度包住内容)、行内让位(文字绕行)。
  • 子级全浮,父级塌陷:父元素高度变 0,边框塌成线,兄弟元素上移重叠。
  • 修复方案:空元素 clear: both(污染 HTML)→ .clearfix::after 伪元素(万能)→ 现代 display: flow-root
  • float 三栏布局是历史遗产,已被 Flex 取代——但老项目里遍地都是,必须看得懂。
  • 现代开发口诀:布局交给 Flex/Grid,float 只做文字环绕。
动手练习:先复现本课的「高度塌陷」——一个带边框的父元素里放三个浮动色块; 再分别用「空元素 clear」和「clearfix」两种方法修复,对比 HTML 的差异; 最后把三个浮动块改成 float: right,观察它们排列顺序的变化(浮动会按 HTML 顺序依次从右往左靠)。