清除浮动这个概念用得有多频繁,每个前端都深有体会。即使并不理解,靠着面试题总结的答案,你也能说出至少三种清除方法。至于为什么需要清除浮动?这些不同的清除方法分别基于什么原理,和大多数的你一样,我曾经也是迷迷糊糊。最近在看《精通WEB-高级Web标准解决方案》,刚好看到这一节,再结合网上一些大牛的文章,如《那些年我们一起清除过的浮动》(个人看过感觉最详细清楚的一篇文章),觉得理解得相对较透彻了。留文于此,一方面便于以后查看,另一方面也是促进与大家的交流。第一篇博文,欢迎指正。
一。为什么清除浮动?
首当其冲的,什么是浮动?
浮动是一种可视化格式模型。浮动的框可以左右移动,直到它的外边缘碰到包含框或另一个浮动框的边缘。
作为css中的重要布局方式,浮动为我们的布局提供了大量便利,同时也因为脱离文档流,出现一些偶尔有用,偶尔又不需要的效果。
1.相邻的块状元素,会把浮动元素视作不存在,钻到浮动元素的下面。
2.相邻元素的文本内容会移动,为浮动元素留出空间。
我们常常利用它来实现文本围绕图片的效果。
3.浮动元素的父元素(未设定高度)坍塌。
我们说的清除浮动,主要也正是针对第三种情况。
二。clear清除过的那些浮动
我不喜欢大篇幅地堆砌清除浮动的方法,接下来,我想从clear着手,用一些具体的场景,一点点啃透clear的用法。
clear的属性可以是left、right、both或none,表示元素框的哪些边不应该挨着浮动框。
很简单的一句话对不对?别急,我保证等下应用的时候你会过头来细细品味这句话的。
1.场景一
假设有三个有色块元素,1、2平行排列,3独占一行,包含在一个具有边框的元素中。
块元素平行排列,你很快想到了浮动,于是你写出以下代码:
.wrapper{
margin: 50px auto;
border:3px solid #000;
width:420px;
}
.float{
float: left;
width:100px;
height:100px;
border:3px solid #000;
background: red
}
.normal{
width:200px;
height:200px;
background: yellow;
border:3px solid #000;
}
<div class="wrapper">
<div class="float"></div>
<div class="float"></div>
<div class="normal"></div>
</div>
但是效果并不完全如你所愿;
没有浮动的元素3一部分藏到了浮动元素的下面,原因正是,浮动元素1、2不占空间,元素3按照它们不存在进行排列。而我们的目标效果是,元素3从元素1、2的下方开始排布。所以,我们需要对元素3的左边清除浮动。
因为我们的清除对象是元素3,因此只要给元素3添加属性clear:left即可;
于是你终于得到了自己的目标效果。
2.场景二
你一定注意到了,场景一的第一幅图中,父元素的高度是靠元素3撑开的。假设我们让元素3的高度变小变小至0,看看会有什么效果。
随着元素3高度的减小,父元素的高度也随时减小,最终的高度数值为多少呢?这段请你考虑一下。当我们把子元素的border全部设为0,效果如下,正是我们理解的父元素坍塌现象。
原因不难理解,场景一种,父元素的高度是靠元素3撑开的,故而当元素3高度减小为0时,父元素亦随之减小。
那么场景二呢?此时,父元素的高度由元素1、2和元素3共同撑开,因此,即使元素3的高度为0,父元素依然可以依靠元素1、2撑开高度。
两幅图进行对比。我们也就得到了清除浮动的一个解决办法,那就是添加一个只有属性clear:both的空元素。
clear清除的到底是谁?由以上的对比分析可以看出,clear清除的是所在对象的元素框。
wrapper:after{
content: ".";
height:0;
visibility:hidden;
display: block;
clear:both
}
同样地,清除浮动另一个常用的方法是在父元素中添加伪类;after,此处更多的是要对after伪类有一个正确的理解。after表示在被选元素的内容后面插入一个虚拟元素,相当于被选元素的子元素,只是没有生成新的dom。这个虚拟元素默认为行内元素。
我们可以看到,除了clear:both起到清除的作用,另外几项的设定其实是让这个新增的虚拟元素内容不可见,且为块状元素。