作为终结篇,竟然是消灭它。。。
好吧,还是先开始吧。
一. clear属性
说道清除浮动,大家恐怕第一个想到的就是clear属性吧。该属性的官方说明如下:
属性名: clear
值: none | left | right | both | inherit
初始值: none
继承性: 无
应用对象:block-level元素
它指明了block-level box(看第21条)不希望自己的 left/ right / both与前面的float box相毗邻。要注意的是,这里清除的是排在block-level box前面的float box,与后面的float box不相干啊。有疑惑的童鞋请翻翻这篇文章的上半部分。
- 设为 left 会使得该box的上边框边缘(top border edge)不高于在它之前的任何向左浮动的float box的下边缘(看第24条)
- 设为 right 会使得该box的上边框边缘(top border edge)不高于在它之前的任何向右浮动的float box的下边缘
- 设为 both 会使得该box的上边框边缘(top border edge)不高于在它之前的任何float box的下边缘
- 设为 none 那就是啥也不做
以上这些都是我们通过代码调节可以直观看见的现象,实际背后有更深层的东西值得我们去挖掘。
二. “清除”引入的条件、“清除”达到的效果、清除公式
1. 条件
首先问个问题: 是不是只要clearence设为非none,就真的会发生浮动清除呢?
当然不是!
如果clearence设为非none, css可能会引入清除。决定是否引入还得看block-level box在没有设置clearence(或者说clearence为none)的情况下所处的位置。
假设block-level box的clearence设为left。现在重置它的clearence为none,看看它的上边框边缘是否高于它之前的任何向左浮动的float box的下边缘。如果高于,则引入清除。
2. 效果
看过前几篇浮动的文章的童鞋都知道,float box可能会与block-level box并排,产生“围绕现象”。那么清除浮动带来的效果就是 block-level box会流动到float box之下,若block-level box与其他box产生了margin重叠, 重叠现象也会消失。
对比一下,或许更清楚!
例一 无清除
- chrome上的效果:
<html> <head> <style type="text/css"> .parent{ width:500px; height:auto; margin:20px auto 0; padding:10px; line-height:30px; font-family:"Times New Roman",Georgia,Serif; border:solid 2px rgba(247, 79, 79, 0.56); } .float-child{ width:100px; height:50px; float:left; margin-right:10px; box-sizing:border-box; background:rgba(247, 79, 79, 0.56); } .normal-child{ width:350px; border:solid 1px rgba(247, 79, 79, 0.56); margin-bottom:5px; padding-left:5px; } .first-block{ margin-bottom:10px; } .second-block{ margin-top:20px; } </style> </head> <body> <div class='parent'> <div class='normal-child first-block'>first block-level box</div> <div class='float-child'></div> <div class='normal-child second-block'>second block-level box</div> </div> </body> </html>
float box看上去完全就是一个土匪嘛,很霸道的挡住第二个block-level box!
另外,第一个block-level box与第二个block-level box也产生了margin重叠,看个像素图。
可以看到,第一个block-level box与第二个block-level box之间的距离取margin的最大值20px,它们的margin发生了重叠。
再去看看清除带来的变化。
例二 引入清除
在例一的基础上修改.second-block类,具体如下:
.second-block{
margin-top:20px;
clear:left;
}
登登登~~~“清除”上场,效果杠杠滴!
第二个block-level box不仅成功的摆脱了float 土匪,还与第一个block-level box划清了界限,margin没有重叠,互不干扰,清的很干净嘛!
由此,可看出清除就如同在block-level box的上方加了一定高度的空白,这会使得block-level box移动到float box之下,并阻止了margin重叠。
看到这,有木有童鞋对block-level box下移的计算过程感兴趣?虽说在实际编程中没啥用处,但是可以在面试官面前装大神。。。。好吧,我接着讲了,不感兴趣的童鞋直接略过下节。
3. 清除公式
用过清除的都知道,block-level box虽说会移动到float box下方,但也不是随意下移的,它每次都会保证border的上边缘与位置最低的被清除float box的下边缘齐平。这是如何做到的呢?计算出block-level box的上边缘与位置最低的被清除float box的下边缘齐平所需要的清除距离(设为C),然后将block-level box下移C。
距离又是怎么算出来的呢?这里有个清除公式。
假设在html文档里有如下几个元素:第一位是margin-bottom为M1的block B1,第二位是高度为H的float box,第三位是margin-top为M2的block B2。B1和B2均没有子box,也没有设置padding或border。另外,B2不为空,且clear为both。那么它们在浏览器上应该表现成酱紫:
因为要引入清除,那么第二个block box必须满足:上边框边缘高于它之前的任何向左浮动的float box的下边缘,也就是:
max(M1,M2) < M1 + H
看上文,我们知道:清除需要保证B2的border的上边缘与位置最低的被清除float box的下边缘齐平,也就是:
F的下边缘 = B2的border的上边缘
M1 + H = M1 + C + M2 (注:M1和M2此时是不会重叠的)
C = M1 + H - M1 - M2
= H - M2
由此,我们知道清除距离
C = H - M2
也许有爱思考的童鞋问道:如果float box有上下margin怎么办?
此时的C = (H + 上margin + 下margin) - M2。
为啥?哈哈,这是因为float box不会与任何box发生margin重叠,所以呢,在有上下margin时得加上margin。
是不是没啥鸟用,^ ^ ~~~
三. 大家口中的清除
常看到某些博文写到,如何清除box内的浮动,清除浮动的N种方法,balabala......一大堆。实际上标准的清除浮动只能清除float box下面的第一个block-level box。
为什么会想到要清除box内的浮动?我想大概是因为某个block box的子float box跑到该block box的外面去了,一些童鞋以为是浮动搞得鬼。
其实这不完全怪浮动。
每个box的高度计算是要遵循一定的规则。overflow为visible,height为auto的block box在计算高度时会忽略子box中的float box的高度,由此造成float box的下边缘跑到block box之外。
还有类似清除浮动的N种方法,大部分是不明白这里面的规则而写的hack方法,这些奇怪的清除方式常常会产生一些不易察觉的bug,大家还是少用为妙。知道背后的机制,再给出正确的解决办法,才是终极之道啊!
浮动终于终于终于写完了,真是大头啊,花了不少时间整理。接下来要去啃下一个大骨头了,byebye啦。
ps: 本文中的例子均是在chrome 49.0上测试。