本文介绍了四种清除浮动的方法,并尝试解释其原理。在理解了各类清除浮动的原理以后,你会发现,不少清除浮动的方法本质上实际上是同样的。掌握这些原理,相信你能够根据场景和需求,灵活运用原则发展出不一样的清除浮动的方法,而再也不死记或拘泥于文中提到的方法。css
在讲清除浮动的方法以前,咱们先来了解一下为何要清除浮动,清除浮动的目的是什么,即,要解决什么样的问题。来看一个浮动的例子(略去了文字内容):html
<div class="topDiv">
<div class="floatDiv">float left</div>
<div class="textDiv">...</div>
</div>
<div class="bottomDiv">...</div>复制代码
其样式为:chrome
.topDiv {
width: 500px;
border: 2px solid black;
}
.floatDiv {
width: 100px;
height: 100px;
border: 2px dotted red;
color: red;
margin: 4px;
float: left;
}
.bottomDiv {
width: 500px;
height: 100px;
margin: 5px 0;
border: 2px dotted black;
}
.textDiv {
color: blue;
border: 2px solid blue;
}复制代码
在chrome中渲染的效果以下图所示:浏览器
这确定不是咱们想要的渲染效果,它可能存在以下问题:bash
.textDiv
)排列在浮动元素下方,或者,咱们并不但愿.textDiv
两边有浮动元素存在。.topDiv
),父元素的高度出现了塌缩,若没有文字高度的支撑,不考虑边框,父级元素高度会塌缩成零。.bottomDiv
)排版。由于浮动元素脱离了文档流,.bottomDiv
在计算元素位置的时候会忽略其影响,紧接着上一个元素的位置继续排列。解决第一个问题,须要清除.textDiv
周围的浮动,而解决第二个问题,由于父元素的兄弟元素位置只受父元素位置的影响,就须要一种方法将父级元素的高度撑起来,将浮动元素包裹在其中,避免浮动元素影响父元素外部的元素排列。ide
接下来开始介绍清除浮动的方法。工具
仍是开篇的例子,咱们给须要清除浮动的元素添加以下样式:性能
.textDiv {
color: blue;
border: 2px solid blue;
clear: left;
}复制代码
清除浮动后的渲染效果以下:学习
解释一下:ui
经过上面的样式,.textDiv
告诉浏览器,个人左边不容许有浮动的元素存在,请清除掉我左边的浮动元素。然而,由于浮动元素(.floatDiv
)位置已经肯定,浏览器在计算.textDiv
的位置时,为知足其需求,将.textDiv
渲染在浮动元素下方,保证了.textDiv
左边没有浮动元素。同时能够看出,父元素的高度也被撑起来了,其兄弟元素的渲染也再也不受到浮动的影响,这是由于.textDiv
仍然在文档流中,它必须在父元素的边界内,父元素只有增长其高度才能达到此目的,能够说是一个意外收获。(clear
的值为both
也有相同的效果,通俗理解就是,哪边不容许有浮动元素,clear就是对应方向的值,两边都不容许就是both
)
可是,若是咱们把HTML中的.floatDiv
和.textDiv
交换一下位置呢?
<div class="topDiv">
<div class="textDiv">...</div>
<div class="floatDiv">float left</div>
</div>
<div class="bottomDiv">...</div>复制代码
不管.textDiv
是否应用清除浮动,状况都是下面的样子:
.textDiv
的位置先肯定了,因而浮动元素就紧接着.textDiv
下方渲染在父元素的左侧。然而,父元素的高度并无被撑起来,没有将浮动影响“内化”,致使浮动影响到了接下来的元素排版。
看来,为达到撑起父元素高度的目的,使用clear
清除浮动的方法仍是有适用范围的。咱们须要更加通用和可靠的方法。
(这里澄清一下,单从元素清除浮动的角度,clear
彻底已经达到了目的,它已经使得.textDiv
特定的方向上再也不有浮动元素,清除浮动其实仅仅针对须要清除浮动的元素自己而言,只关注自身需求是否达到,和外界没有什么关系,它不关注浮动是否超出父元素,以及浮动是否影响到后续元素排列。咱们只是利用了浮动的一些特性达到某些目的,但这不是清除浮动关心的问题,只不过,相对于清除浮动,咱们可能更加关心这些特性能为咱们作些什么而已。个人理解是,清除浮动和撑起父元素高度实际上是两个不一样的问题,在这里,能够简单地理解为工具和目的之间的关系,接下来要讨论的两个方法都是在利用清除浮动这个工具在解决问题,它并非清除浮动这个工具自己。不过,咱们常常将二者混为一谈。sorry,有点啰嗦,看不懂就是我没表达清楚,跳过便可。。。)
HTML结构以下,在有浮动的父级元素的末尾插入了一个没有内容的块级元素div:
<div class="topDiv">
<div class="textDiv">...</div>
<div class="floatDiv">float left</div>
<div class="blankDiv"></div>
</div>
<div class="bottomDiv">...</div>复制代码
应用样式:
.topDiv {
width: 500px;
border: 2px solid black;
}
.floatDiv {
width: 100px;
height: 100px;
border: 2px dotted red;
color: red;
margin: 4px;
float: left;
}
.bottomDiv {
width: 500px;
height: 100px;
margin: 5px 0;
border: 2px dotted black;
}
.textDiv {
color: blue;
border: 2px solid blue;
}
// 区别在这里
.blankDiv {
clear: both; // or left
}复制代码
渲染效果以下:
原理无需多讲,和第一个例子里.textDiv
应用clear清除浮动,撑起父级元素高度的原理彻底同样。这里强调一点,即,在父级元素末尾添加的元素必须是一个块级元素,不然没法撑起父级元素高度。
HTML结构以下,为了惯例相符,在.topDiv
的div上再添加一个clearfix
类:
<div class="topDiv clearfix">
<div class="textDiv">...</div>
<div class="floatDiv">float left</div>
</div>
<div class="bottomDiv">...</div>复制代码
样式应用以下:
// 省略基本的样式
// 区别在这里
.clearfix:after {
content: '.';
height: 0;
display: block;
clear: both;
}复制代码
该样式在clearfix
,即父级元素的最后,添加了一个:after
伪元素,经过清除伪元素的浮动,达到撑起父元素高度的目的。注意到该伪元素的display
值为block
,即,它是一个不可见的块级元素(有的地方使用table
,由于table
也是一个块级元素)。你可能已经意识到,这也只不过是前一种清除浮动方法(添加空白div)的另外一种变形,其底层逻辑也是彻底同样的。前面的三种方法,其本质上是同样的。
首先直观地看看,overflow
是如何清除浮动的。
HTML结构以下:
<div class="topDiv">
<div class="floatDiv">float left</div>
<div class="textDiv">...</div>
</div>
<div class="bottomDiv">...</div>复制代码
样式应用以下:
.topDiv {
width: 500px;
padding: 4px;
border: 2px solid black;
// 区别在这里
overflow: auto;
}
.floatDiv {
width: 100px;
height: 100px;
border: 2px dotted red;
color: red;
margin: 4px;
float: left;
}
.bottomDiv {
width: 500px;
height: 100px;
margin: 5px 0;
border: 2px dotted black;
clear: both;
}
.textDiv {
color: blue;
border: 2px solid blue;
}复制代码
不该用上面标识出来的CSS时,渲染结果和本文开始的第一个图形效果相同,应用CSS后的渲染效果以下:
仅仅只在父级元素上添加了一个值为auto的overflow属性,父元素的高度当即被撑起,将浮动元素包裹在内。看起来,浮动被清除了,浮动再也不会影响到后续元素的渲染(严格讲,这和清除浮动没有一点关系,由于不存在哪一个元素的浮动被清除,不纠结这个问题)。其实,这里的overflow值,还能够是除了"visible"以外的任何有效值,它们都能达到撑起父元素高度,清除浮动的目的。不过,有的值可能会带来反作用,好比,scroll值会致使滚动条始终可见,hidden会使得超出边框部分不可见等。那它们是如何作到浮动清除的呢?
要讲清楚这个解决方案的原理,有一个概念始终是绕不过去,那就是块格式化上下文(BFC),然而这又是一个很是抽象的概念,若是要清楚地把这个概念讲出来,恐怕须要很是大的篇幅,这里仅说起和理解该问题相关的内容。
这是从MDN上摘下来的BFC定义:
A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.
翻译过来就是:块级格式化上下文是CSS可视化渲染的一部分。它是一块区域,规定了内部块盒的渲染方式,以及浮动相互之间的影响关系。
块格式化上下文(BFC)有下面几个特色:
有了这几点,就能够尝试解释为何overflow
(值不为visible
)能够清除浮动了。
当元素设置了overflow
样式,且值不为visible
时,该元素就建构了一个BFC(哪些状况下,元素能够建构出BFC,能够看查看CSS文档对BFC的定义)。在咱们的例子中,.topDiv
因设置了值为auto
的overflow
样式,因此该元素建构出一个BFC,按照第三个特色,BFC的高度是要包括浮动元素的,因此.topDiv
的高度被撑起来,达到了清除浮动影响的目的。(至于为何值为visible
的overflow
不能建构BFC,这个答案给了一个解释)
其实,这里overflow的做用就是为了构建一个BFC区域,让内部浮动的影响都得以“内化”。若是你看了BFC的定义,你会发现,构建一个BFC区域的方法有不少种,overflow
只是其中的一种,那在这里,咱们是否也能够利用其它的方式构建BFC,且一样能达到清除浮动的目的呢?
BFC定义中说,inline-block
一样也能构建BFC,那咱们就用该样式来试试:
.topDiv {
width: 500px;
padding: 4px;
border: 2px solid black;
// 区别在这里
display: inline-block;
}
// 其余样式相同,省略复制代码
渲染效果以下:
效果彻底同样!只要咱们理解了原理,就能够灵活演变出不一样的清除浮动的方法,而没必要死记某种手段。
固然,要说明的是,在实际项目中选择采用哪一种方式构建BFC是要具体问题具体分析的,由于要考虑到选用的样式自身的做用和影响。这个例子中,选用inline-block
和选用overflow
效果彻底同样,没有看出有什么反作用,但不表明在其余项目中同样能行得通。甚至对overflow
值的选择也要考虑其表现和影响。在各类构建BFC的方式中,overflow
方式多是外部影响更可控的一种,我猜测这也许就是为何广泛采用overflow
来清除浮动的缘由吧。
到这里,我要分享的清除浮动的方法已经讲完了。其实,若是在不一样的使用场景下,对这几个方法进行拆分组合(实际上是对底层原理的拆分组合),还能够实现其余形式不一样的清除浮动的方法,最重要的仍是对底层原理的把握。知其然,亦知其因此然才是最有效的学习方式。
下面是文中涉及的连接汇总:
水平有限,文章中不免会出现不许确,甚至错误的地方,期待你的宝贵意见!