重学css(9)——那些年骗过你的float和“清浮动”
1.探究图片环绕文字的传说
在深入了解float之前,相信大家都听过一个传说,就是float被设计出来的目的是为了实现文字环绕图片的效果,可能是初学的时候忘了,还是受了“清浮动”的毒,我自己都忘了有没有用float去实现过这个效果。因此下面我们先来实现一下float的设计初衷,文字环绕图片效果。
<div style="width: 200px">
<div style="float: left;">
<img width="100" height="100" src="../小和尚.jpg">
</div>
<p>我想实现文字环绕,因此需要多一些文字看一下效果我想实现文字环绕,因此需要多一些文字看一下效果</p>
</div>
非常简单的一段代码,也不需要什么牛逼哄哄的操作,float就帮助我们实现了文字环绕图片的效果。为了实现这种效果,CSS设计师在设计float属性的时候定义了float的两个特性。
(1)“破坏文档流”,使得父元素得高度塌陷。
(2)禁止行框盒子与浮动元素发生重叠。
下面我们结合这两个特性,来说说图片是如何环绕文字的。第一点,破坏文档流,使得父元素高度塌陷,这个时候,我们的p标签作为一个block元素,肯定是想着我要填满父容器的宽度,而事实上,块级元素也是不辱使命的完成了自己的任务,我们可以给块级标签加个背景色,然后把图片搞成小透明,看一下是不是这样。
果然,第一个条件生效了,然而高度塌陷只是让浮动元素和块级元素在一个水平线上了,如何实现文字环绕效果呢?这个时候就需要我们的第二个属性出场了,就是float元素禁止与行框盒子发生重叠(个人认为这是float和绝对定位的最大区别之一),对“行框盒子”还不理解的童鞋请转内联元素那章。注意,我特意强调了行框盒子,也就是本例中匿名内联元素生成的每一行,这个跟块级元素的盒子没有半毛钱关系。为了验证这个想法,我们可以把p标签转化成内联元素(display:inline)看下效果。为了看上去更明显,我把图片的透明度设成了0,可以看到,浮动元素确实是和行框盒子发生了不重叠的关系。-
至此,我们已经完全了解了那个float的传说。
2.浮动锚点和浮动参考?听都没听过!
我估计在座的各位和我一样(是个辣鸡),都是第一次听说浮动锚点和浮动参考,更别说去了解特么的概念了。干巴巴的讲概念在CSS世界里根本行不通,很多东西都要通过实践,确认过眼神才能够去猜测其内部的原理。那么我们就通过一个例子来了解一下这两个概念。
<!-- 测试浮动参考 -->
<div style="width: 200px;text-align: justify;background: yellow">
<span>这里有很多文字,且要超出一行且要超出一行且要超出一行</span>
<span style="float: right;color:blue">更多</span>
</div>
首先上面这个例子,文字超出一行的时候,浮动元素会浮在哪儿?是文字的第一行?还是文字的最后一行?还是随便浮?答案是,最后一行,看一下具体效果就知道了。
由于markdown编辑器支持标签语言,因此我们可以直接预览最终效果如下(小提示:你可以通过浏览器直接检查下面的元素看到CSS样式)
结果已经出来了,那么,为什么呢?
这个时候就要邀请我们的浮动参考出场了。浮动参考,顾名思义,就是指float元素要对齐参考的实体是谁?
在CSS世界中,float元素的浮动参考是“行框盒子”,这个行框盒子特么又出来了,怎么感觉哪儿都有它。注意是行框盒子,跟其父容器子元素等等等等都没半毛钱关系。这里作者温馨提示,在新的标准中,float的浮动参考不仅仅是行框盒子,但他没有展开,我也懒得查阅,就当留个悬念。知道了浮动参考的概念后,我们就可以解释上面这个例子了,由于float元素是参考行框盒子对齐的,因此,float可能在第一行,也可能在第二行,为什么在第三行呢?
这里其实作者没有说明,我提出一个假设,就是浮动元素参考的是离他最近的行框盒子,这个观点由本人提出,由本人验证后发现事实就是这样,所以有时候CSS的世界就是瞎猜一通然后验证。下面我来简单验证一下这个观点,其实很简单,只要把浮动元素放到span标签前面就可以了。如下所示
<!-- 验证浮动参考是离他最近的行框盒子 -->
<div style="width: 200px;text-align: justify;background: yellow">
<span style="float: right;color:blue">更多</span>
<span>这里有很多文字,且要超出一行且要超出一行且要超出一行</span>
</div>
由于markdown编辑器支持标签语言,因此我们可以直接预览最终效果如下(小提示:你可以通过浏览器直接检查下面的元素看到CSS样式)
image.png结果完全印证了我的想法是正确的,我吹爆我自己!
说完了浮动参考,那么什么是浮动锚点?浮动锚点是float元素所在流中的一个点,你可以理解为是一个空的内联元素,为什么要有这个点呢?道理很简单,有时候我们的浮动元素没有可以参考的行框盒子,也就是他的四周都被一群block大汉包围的时候该怎么办?往哪里定位?没有关系,他自己带一个可以参考的浮动锚点。由于这个属性没什么特殊之处,这里就不过多介绍了,了解一下就好。
3.那些年你被骗过的clear“清浮动”
相信我们初学浮动的第一课便被灌输了“浮动”破坏文档流是个祸害的思想,为了解决浮动元素导致高度坍塌的“bug”,我们被要求清浮动。然后给了一大堆清浮动的方法,最后提出最好用的是after伪类清浮动,当时还真觉得煞有其是,现在看来真的是人言可畏。如果CSS自家制定的标准都被当作了bug,那还有什么不是bug呢?
看完这一章后,你应该可以明白两个概念:第一,浮动引起的高度坍塌是为了解决图文环绕效果而被制定的标准,并不是所谓的bug。第二,所谓的clear清浮动,并没有清除掉浮动。
为什么说clear没有清除掉浮动呢?从字面意思上理解,clear确实是清除的意思,然而官方对于clear的解释是:元素盒子的边不能和前面的浮动元素相邻。
这句话听起来很拗口,但可以明确的知道,clear并没有改变任何浮动元素的特性,浮动元素依旧是那个浮动元素,不管你清不清,他还是在那边,浮着。
那么这句话的涵义是什么呢?仔细剖析一下,你会发现,“清浮动”的奥秘就在于这个不能相邻的标准。事实上,clear被制定出来就是为了解决口耳相传的“高度坍塌bug”,因此浮动元素本身的特性被完美保留。概念讲的干了,来看一个例子吧
<!-- 清浮动原理探究 -->
<div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
</div>
<style>
.li{
float: left;
margin: 10px;
width: 40px;
height: 40px;
background: yellow
}
.li:nth-of-type(3){
clear: both;
}
</style>
上面这个例子,最终li会被清浮动分割成几行?
最终结果是:两行。由于markdown编辑器支持标签语言,因此我们可以直接预览最终效果如下(小提示:你可以通过浏览器直接检查下面的元素看到CSS样式)
image.png
我们用所学的理论知识来解释下为什么是两行,在样式表中,第三个浮动元素使用了清浮动的属性,此时,根据标准,当前元素不能和前面的浮动元素相邻,也就是第三个元素不能和第二个元素做朋友了,那只能换行了,然而标准没有规定第三个元素不能和后面的元素做朋友,因此第三个元素以及之后的元素依旧保持左浮动的特性规则排列。由于第一行和第二行都保持了浮动的特性,因此高度全部坍塌,此时父级容器div的高度依旧是0,不会因为清了浮动,父容器的高度就变成第一行的高度了,父容器高度依旧是0!注意是0!(由于我直接用了标签去展示结果,父元素高度坍塌会导致文章排版出问题,因此F12检查元素的时候会发现父元素高度不是0,是因为利用了BFC特性加了overflow,这个在下一章会详细探讨)
看完了上面的例子,再来简单了解下clear的四个属性,分别是none(默认,就是没有),left(清左浮动),right(清右浮动)以及我们最常用的both(全清)。作者这里给出了clear的基本使用方式就是clear:both。left和right属性根本没有软用,让CSS自己判断就好了,因为不可能有一个元素既是left又是right浮动的,因此无需考虑是清左浮动还是右浮动,全清就完事了。
由于clear只能确保和前面的元素发生关系,因此我们最常使用的是after伪类清浮动,而不是before,因为before生成的元素根本没法和后面的元素交流clear的事情。最后我们放上我们最喜欢使用的after伪类清浮动的方法,注意clear属性只有块级元素才有效,而伪类的默认属性是内联值,不要忘了display:block申明。
<div class="clearfix">
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
<div class="li"></div>
</div>
<style>
.li{
float: left;
margin: 10px;
width: 40px;
height: 40px;
background: yellow
}
.li:nth-of-type(3){
clear: both;
}
.clearfix::after{
content: '';
display: block;
clear: both;
}
</style>
复制代码
image.png
本章到这里其实还没有结束,下一章的内容会继续探讨float的BFC特性,以及如何用overflow真正的清除浮动。
最后,给大家推荐一个前端学习进阶内推交流群685910553(前端资料分享),不管你在地球哪个方位,
不管你参加工作几年都欢迎你的入驻!(群内会定期免费提供一些群主收藏的免费学习书籍资料以及整理好的面试题和答案文档!)
如果您对这个文章有任何异议,那么请在文章评论处写上你的评论。
如果您觉得这个文章有意思,那么请分享并转发,或者也可以关注一下表示您对我们文章的认可与鼓励。
愿大家都能在编程这条路,越走越远。