浮动与清除浮动
问题
浮动的原理是什么?为什么浮动会导致父元素高度塌陷?如何清除浮动?
答案
浮动的基本概念
float 最初是为了实现文字环绕图片的排版效果。浮动元素会脱离正常文档流,向左或向右浮动,直到碰到容器边缘或另一个浮动元素。
.float-left { float: left; }
.float-right { float: right; }
.float-none { float: none; } /* 默认值 */
浮动的特性
- 脱离文档流:不再占据正常流中的空间
- 行内框会避让:文本和行内元素会环绕浮动元素(这是 float 的本意)
- 块级元素无视浮动:块级元素会当浮动元素不存在,占据浮动元素的空间
- 浮动元素变为块级:任何元素浮动后
display变为block - 浮动元素贴靠:连续浮动元素会在水平方向依次排列
┌─────────────────────────────┐
│ ┌─────┐ 这是一段文字,会环绕 │
│ │ img │ 在浮动的图片旁边。当 │
│ │float│ 文字足够多时,会继续 │
│ └─────┘ 在图片下方排列。 │
│ 之后的文字占满整行宽度。 │
└─────────────────────────────┘
高度塌陷问题
当子元素全部浮动时,父元素的高度会变为 0(高度塌陷),因为浮动元素脱离了文档流:
<div class="parent">
<!-- 所有子元素浮动 → 父元素高度为 0 -->
<div class="child" style="float: left;">子元素1</div>
<div class="child" style="float: left;">子元素2</div>
</div>
<div class="footer">我会跑到 parent 里面去</div>
┌──────────────── parent(高度 = 0)──┐
└────────────────────────────────────┘
┌────┐ ┌────┐ ← 浮动子元素脱离文档流
│子1 │ │子2 │
└────┘ └────┘
┌─── footer(和浮动元素重叠)─────────┐
清除浮动的方法
方法 1:clearfix 伪元素(推荐)
.clearfix::after {
content: '';
display: block;
clear: both;
}
<div class="parent clearfix">
<div style="float: left;">子元素1</div>
<div style="float: left;">子元素2</div>
</div>
方法 2:触发 BFC
父元素触发 BFC 后会包含浮动子元素:
/* 推荐 */
.parent { display: flow-root; }
/* 其他方式(有副作用) */
.parent { overflow: hidden; } /* 可能裁剪内容 */
.parent { overflow: auto; } /* 可能出现滚动条 */
.parent { display: inline-block; } /* 改变 display */
display: flow-root 是专门为清除浮动设计的,没有 overflow: hidden 的裁剪副作用,是现代 CSS 中最推荐的 BFC 触发方式。
方法 3:clear 属性
在浮动元素后面添加一个带 clear 的元素:
<div class="parent">
<div style="float: left;">子元素</div>
<div style="clear: both;"></div> <!-- 清除浮动 -->
</div>
/* clear 属性值 */
.clear {
clear: left; /* 不允许左侧有浮动元素 */
clear: right; /* 不允许右侧有浮动元素 */
clear: both; /* 两侧都不允许 */
clear: none; /* 默认,允许浮动 */
}
各方法对比
| 方法 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|
clearfix::after | 无副作用、语义清晰 | 需额外类名 | ⭐⭐⭐⭐⭐ |
display: flow-root | 最简洁、语义正确 | IE 不支持 | ⭐⭐⭐⭐⭐ |
overflow: hidden | 简单 | 可能裁剪内容 | ⭐⭐⭐ |
| 空 div + clear | 简单直接 | 增加无语义元素 | ⭐⭐ |
| 父元素也浮动 | 能包含子浮动 | 影响父元素布局 | ⭐ |
现代替代方案
在现代 CSS 中,浮动已经很少用于布局,应优先使用:
| 需求 | 推荐方案 |
|---|---|
| 水平排列 | Flexbox |
| 二维布局 | Grid |
| 文字环绕 | float(唯一合理场景) |
| 多列布局 | column-count / column-width |
常见面试问题
Q1: 为什么浮动会导致父元素高度塌陷?
答案:
浮动元素脱离了正常文档流,父元素在计算高度时不会将浮动子元素纳入计算,因此如果所有子元素都浮动,父元素的高度就会变为 0。
这不是 bug 而是设计如此——float 的本意是文字环绕,浮动元素不影响块级容器的高度,但行内内容会围绕它排列。
Q2: 清除浮动有哪些方法?推荐哪种?
答案:
5 种方法:
- clearfix 伪元素:
.clearfix::after { content: ''; display: block; clear: both; } - BFC -
display: flow-root:父元素直接设置 - BFC -
overflow: hidden/auto:有裁剪/滚动条副作用 - 空元素 clear:添加无语义 DOM
- 父元素也浮动:影响整体布局
推荐 clearfix 伪元素 或 display: flow-root(不兼容 IE 时)。
Q3: clear 属性的原理是什么?
答案:
clear 让元素的上边缘移动到前面所有浮动元素的下方。本质是增加了该元素的 margin-top 来避开浮动元素。
clear: left— 上边缘必须在左浮动元素下方clear: right— 上边缘必须在右浮动元素下方clear: both— 上边缘必须在所有浮动元素下方
Q4: float 和 position: absolute 有什么区别?
答案:
| 特性 | float | position: absolute |
|---|---|---|
| 脱离文档流 | 部分(行内内容仍然环绕) | 完全脱离 |
| 行内内容 | 会环绕浮动元素 | 完全无视 |
| 影响兄弟元素 | 行内元素会让出位置 | 完全覆盖 |
| 触发 BFC | 是 | 是(fixed 也是) |
| 适用场景 | 文字环绕 | 叠加/弹窗/定位 |
Q5: 现在还需要使用 float 布局吗?
答案:
不推荐用 float 做布局。Flexbox 和 Grid 完全替代了 float 的布局能力,且更强大、更易维护。float 唯一合适的场景是文字环绕图片。
维护老项目时仍然需要理解 float,但新项目应该使用 Flex/Grid。
Q6: 什么是 BFC?它和清除浮动有什么关系?
答案:
BFC(Block Formatting Context)是一个独立的布局区域,其特性之一是包含内部的浮动元素。触发父元素 BFC 后,父元素会将浮动子元素纳入高度计算,从而"清除"高度塌陷。
详见 BFC 详解。