CSS 浮动 (Float)
虽然 Flexbox 和 Grid 已经成为了现代布局的主流,但 浮动 (Float) 依然存在于大量旧项目中,且在该机制下的特定行为(如文字环绕)是其他布局无法替代的。理解浮动及其“副作用”(高度塌陷)是 CSS 进阶的必修课。
1. 浮动的本质
float 属性最初被设计出来的唯一目的,是实现报纸版面那样的 “文字环绕图片” 效果。 只是在 CSS 早期(Flexbox 诞生前),开发者发现它能让块级元素并排显示,于是它被“误用”为了网页布局的主力军长达 10 年之久。
1.1 属性值
left: 元素靠左浮动。

right: 元素靠右浮动。

none: 默认值,不浮动。

inline-start/inline-end: 逻辑属性,跟随文字书写方向(现代浏览器支持)。
1.2 浮动的核心行为
当一个元素被设置了 float: left:
- 脱离文档流:它不再占据原来的垂直空间,后续的块级元素会无视它,直接向上补位(钻到它底下)。
- 内容挤压:虽然它脱离了文档流,但后续元素里的文本内容(Inline boxes)依然能“感知”到浮动元素的存在,并会缩短行宽以避开它 —— 这就是文字环绕的原理。
- 吸附边缘:它会向左(或向右)移动,直到碰到父容器的边缘或者另一个浮动元素的边缘为止。
- 行内变块级:浮动后的元素(即使是
<span>)会自动变成块级框(类似display: block),可以设置宽、高、内边距等。
2. 浮动引发的问题:高度塌陷 (Height Collapse)
这是浮动布局中最著名的“副作用”。
现象: 父容器没有设置固定高度 (height: auto)。当其内部所有子元素都浮动后,父容器会认为内部“空了”,导致父容器高度变为 0。
后果:
- 父容器的背景色/背景图消失。
- 父容器下方的其他内容(如页脚)会跑上来,与浮动元素重叠。
3. 清除浮动 (Clearfix) 的 4 种方案
要解决高度塌陷,我们需要让父容器重新“感知”到浮动子元素的高度。
3.1 overflow (BFC 法) —— 推荐用于简单场景
给父容器触发 BFC (块级格式化上下文)。
.parent {
/* overflow: hidden; <-- 最常用,但小心内容溢出被切断 */
/* display: flow-root; <-- 现代最佳方案,无副作用 */
display: flow-root;
}- 原理:BFC 区域在计算高度时,规定必须包含浮动元素。
- 缺点:
overflow: hidden可能会把下拉菜单或阴影切掉;flow-root兼容性需要注意(IE 不支持)。
3.2 ::after 伪元素 (Micro Clearfix) —— 行业标准
这是最经典、兼容性最好的方案。给父容器添加一个类名(如 .clearfix)。
/* 核心代码 */
.clearfix::after {
content: ""; /* 1. 必须有内容(哪怕是空) */
display: table; /* 2. 转换为块级表格上下文 (比 block 更稳) */
clear: both; /* 3. 清除左右浮动 */
}
/* 兼容旧版 IE (可选) */
.clearfix {
*zoom: 1;
}- 原理:在父容器内容的最后面,由 CSS 自动生成一个看不见的“墙”,这堵墙声明了
clear: both,不允许左右有浮动元素,从而强行撑开了父容器。
3.3 空标签法 (不推荐)
在 HTML 里手动加一个空的 div。
<div class="parent">
<div class="float-left">...</div>
<div class="float-left">...</div>
<!-- 手动加个空 div -->
<div style="clear: both;"></div>
</div>- 缺点:在 HTML 里引入了无意义的结构,代码不干净。
3.4 父元素也浮动 (不推荐)
让父元素也 float: left。
- 缺点:拆东墙补西墙。父元素虽然有了高度,但父元素自己又脱离文档流了,会影响父元素的父元素布局。
4. clear 属性详解
clear 属性用于指定元素的哪一侧不允许出现浮动元素。
| 值 | 描述 |
|---|---|
left | 元素的左侧不允许有浮动元素(如果左边有,我就换行,排到它下面去)。 |
right | 元素的右侧不允许有浮动元素。 |
both | 左右两侧都不允许(通常用于清除浮动)。 |
常见误区: clear 属性是设置在不想受浮动影响的那个元素身上的,而不是设置在浮动元素身上的。
5. 浮动布局常见问题 (FAQ)
5.1 为什么我的浮动元素换行了?
原因:宽度计算不够精确。 假设容器宽 100%,你有两个子元素,宽度设为 50%。
- 如果给它们加了
border: 1px或者padding,且没有设置box-sizing: border-box,它们的实际宽度会超过 50%,导致一行放不下,第二个元素被挤到下一行。
解法:始终使用 box-sizing: border-box;或者使用 calc(50% - 2px) 预留空间。
5.2 为什么 text-align: center 对浮动元素无效?
原因: text-align 只能控制行内元素(inline/inline-block)的对齐。 浮动元素虽然变成了块级,但它们已经脱离了常规文档流,父容器的文字对齐规则管不到它们。
解法:若要居中浮动元素,很难直接做。通常需要定宽,然后配合 margin-left 计算。
建议:改用 flex 布局 (justify-content: center),一秒解决。
5.3 浮动元素会被 position: absolute 覆盖吗?
答案:是的。 absolute 的脱离文档流程度比 float 更彻底。
float还在“半空”,文字还能看见它(环绕)。absolute直接“升空”,完全无视浮动元素,直接盖在上面(除非调整 z-index)。
5.4 什么时候还应该用 Float?
在 2024+ 年,不要再用 Float 做页面整体布局(如侧边栏+主内容)。 请仅在以下场景使用 Float:
- 真正的图文环绕:文章中的图片左对齐或右对齐,文字包围它。这是 Flex/Grid 做不到的。
- 兼容极老旧浏览器:如 IE8/9(现在极少见)。
6. 总结:现代布局迁移建议
如果你正在维护旧代码,理解上述的 clearfix 和塌陷原理至关重要。 如果你在写新代码,请遵循以下对照表:
| 需求 | 旧做法 (Float) | 新做法 (Modern CSS) | 优势 |
|---|---|---|---|
| 多列布局 | float: left + 百分比宽度 | display: flex | 自动等高,轻松对齐 |
| 网格系统 | 复杂的 float + clear | display: grid | 代码减少 80%,二维控制 |
| 图文混排 | float: left | float: left | Float 依然是这块的王者 |
| 清除浮动 | .clearfix::after | display: flow-root | 无需 Hack 代码 |