跳到主要内容

浮动与清除浮动

问题

浮动的原理是什么?为什么浮动会导致父元素高度塌陷?如何清除浮动?

答案

浮动的基本概念

float 最初是为了实现文字环绕图片的排版效果。浮动元素会脱离正常文档流,向左或向右浮动,直到碰到容器边缘或另一个浮动元素。

.float-left  { float: left; }
.float-right { float: right; }
.float-none { float: none; } /* 默认值 */

浮动的特性

  1. 脱离文档流:不再占据正常流中的空间
  2. 行内框会避让:文本和行内元素会环绕浮动元素(这是 float 的本意)
  3. 块级元素无视浮动:块级元素会当浮动元素不存在,占据浮动元素的空间
  4. 浮动元素变为块级:任何元素浮动后 display 变为 block
  5. 浮动元素贴靠:连续浮动元素会在水平方向依次排列
┌─────────────────────────────┐
│ ┌─────┐ 这是一段文字,会环绕 │
│ │ 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
.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

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 种方法:

  1. clearfix 伪元素.clearfix::after { content: ''; display: block; clear: both; }
  2. BFC - display: flow-root:父元素直接设置
  3. BFC - overflow: hidden/auto:有裁剪/滚动条副作用
  4. 空元素 clear:添加无语义 DOM
  5. 父元素也浮动:影响整体布局

推荐 clearfix 伪元素display: flow-root(不兼容 IE 时)。

Q3: clear 属性的原理是什么?

答案

clear 让元素的上边缘移动到前面所有浮动元素的下方。本质是增加了该元素的 margin-top 来避开浮动元素。

  • clear: left — 上边缘必须在左浮动元素下方
  • clear: right — 上边缘必须在右浮动元素下方
  • clear: both — 上边缘必须在所有浮动元素下方

Q4: float 和 position: absolute 有什么区别?

答案

特性floatposition: absolute
脱离文档流部分(行内内容仍然环绕)完全脱离
行内内容会环绕浮动元素完全无视
影响兄弟元素行内元素会让出位置完全覆盖
触发 BFC是(fixed 也是)
适用场景文字环绕叠加/弹窗/定位

Q5: 现在还需要使用 float 布局吗?

答案

不推荐用 float 做布局。Flexbox 和 Grid 完全替代了 float 的布局能力,且更强大、更易维护。float 唯一合适的场景是文字环绕图片

维护老项目时仍然需要理解 float,但新项目应该使用 Flex/Grid。

Q6: 什么是 BFC?它和清除浮动有什么关系?

答案

BFC(Block Formatting Context)是一个独立的布局区域,其特性之一是包含内部的浮动元素。触发父元素 BFC 后,父元素会将浮动子元素纳入高度计算,从而"清除"高度塌陷。

详见 BFC 详解

相关链接