1. 什么是浮动
《精通CSS》(第3版)关于浮动的描述:
浮动盒子可以向左或向右移动,直到其外边沿接触包含块的外边沿,或接触另一个浮动盒子的外边沿。
浮动盒子也会脱离常规文档流,因此常规流中的其他块级盒子的表现,几乎当浮动盒子根本不存在一样。
为什么说“几乎”?因为其他元素盒子中的文本内容会记住浮动元素的大小,并在排布时避开它,为其留出相应的空间。从技术角度来讲,就是跟在浮动元素后面的行盒子会缩短,从而为浮动元素留空,造成文本环绕浮动盒子的效果。事实上,浮动就是为了在网页中实现文本环绕图片的效果而引入的一种布局模型。
关于包含块的描述:
确定元素的包含块,要看元素是如何定位的。
如果元素的定位方式为静态定位(即不指定position
属性的值)或相对定位,则其包含块的边界就计算到一个最近的父元素,该元素的display
属性值必须能够提供类似块级的上下文。
默认情况下,width
、height
、margin
和padding
的值为百分比时,就以该父元素的尺寸为计算依据。
关于格式化上下文的描述:
元素在页面上水平或垂直排布时的一套规则叫作格式化上下文。
格式化上下文又分为:
- 行内格式化上下文
- 块级格式化上下文
先看一个例子。
<style>
.child {
100px;
height:100px;
}
.child1 {
background-color:red;
}
.child2 {
background-color:yellow;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child child1"></div>
<div class="child child2"></div>
</div>
div
是块级元素,它独占一行。现在我们使用浮动。
.child1 {
float:left;
background-color:red;
}
我们发现背景色为黄色的div
(简称"黄色div
")在页面中不见了。事实上,这是由于使用了浮动的div
脱离常规文档流,而常规流中的元素排列时当这个浮动的div
不存在一样。
我们覆盖黄色div
的样式,宽度改为200px
。
.child2 {
200px;
background-color:yellow;
}
我们这时看到了黄色div
了,不过它看上去像是紧跟在红色div
后面,宽度为100px
。事实上,黄色div
的宽度为200px
,其中的100px
被浮动的红色div
挡住而已。
2. 清除浮动的几种方法
2.1 使用clear属性
清除浮动使用clear
属性,《精通CSS》(第3版)关于该属性的描述:
要阻止行盒子环绕在浮动盒子外面,需要给包含行盒子的元素应用
clear
属性。clear
属性的值有left
、right
、both
和none
,用于指定盒子的哪一侧不应该紧挨着浮动盒子。
.child {
100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
.child2 {
200px;
background-color:yellow;
clear:left;
}
上面就是清除浮动的效果,我们终于看到了宽度为200px
的黄色div
,它没有被浮动的红色div
挡住了。
简而言之,我们说clear
属性指定元素哪一侧不能出现浮动元素。红色div
的位置已经确定,黄色div
的左边又不能有浮动元素,因此,黄色div
渲染到了红色div
下方。
2.2 使用:after伪类
我们可以使用:after
伪类来模拟额外的清除元素。
<style>
.child {
100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
.child1Wrapper:after {
content:'';
display:block;
clear:both;
}
.child2 {
200px;
background-color:yellow;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child1Wrapper">
<div class="child child1"></div>
</div>
<div class="child child2"></div>
</div>
没有清除浮动时,父元素的高度塌陷为0
。
<style>
.parent {
200px;
padding:5px;
background-color:gray;
}
.child {
100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child1Wrapper">
<div class="child child1"></div>
</div>
</div>
清除了浮动之后,父元素就有高度了。
.child1Wrapper:after {
content:'';
display:block;
clear:both;
}
为什么父元素有高度了呢?这其实跟块级格式化上下文有关系。参考阅读:为什么"overflow:hidden"能清除浮动的影响
上述参考阅读引出了下面将要讲的overflow:hidden
。
3. overflow:hidden清除浮动的原理
<style>
.child {
100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
.child2 {
200px;
background-color:yellow;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child1Wrapper">
<div class="child child1"></div>
</div>
<div class="child child2"></div>
</div>
在浮动元素的父元素上使用overflow: hidden
。
.child1Wrapper {
overflow: hidden;
}
使用overflow: hidden
时,实际上就创建了一个块级格式化上下文,该块级格式化上下文决定了height:auto
(不设置height
时,其默认值为auto
)是如何计算的。
计算块级格式化上下文的高度时,浮动元素也参与计算。因此,父元素在计算其高度时,加入了浮动元素的高度,就达到了清理浮动的效果。
参考:
- 《精通CSS》— [英] 安迪·巴德、[瑞典] 埃米尔·比约克隆德
- 为什么"overflow:hidden"能清除浮动的影响
- 清除浮动的四种方式及其原理理解