完全理解float之“不完全脱离文档流”

0.前言
float属性在css2中是一个热门的属性 , 被广泛应用于布局之中 , 同时由于不当使用float带来的问题也非常多,本文结合自己对float的理解以及实际项目中碰到float的相关问题,做一个详细总结,欢迎一起探讨,但未经同意禁止转载 。以下是文章的目录
float的特性
float与的区别
float与-block
清除浮动的方法及优缺点
1. float的特性文字环绕
float 最早的设计目的是用于图片,使文字能够环绕在图片周围 , 像下面这样:

完全理解float之“不完全脱离文档流”

文章插图

完全理解float之“不完全脱离文档流”

文章插图
文字环绕效果是很明显的,这里要注意一个地方:浮动的块虽然脱离的正常的文档流,但是还会占有正常文档流的文本空间,可以看到上面第二种图,p的区域其实是顶到了img的底下的,因为float让img脱离文档流,但是p上的文字却没有顶过去 , 也就是说p上的一部分文字空间仍然被img占据着,所以从这里也可以看出float的脱离文档流不是完全脱离 。
包裹性
所谓的包裹性是指 , 使用float的元素会自动加上一个块级框,也就是可以像块级元素那样设置宽高
,例子如下:
完全理解float之“不完全脱离文档流”

文章插图

完全理解float之“不完全脱离文档流”

文章插图
破坏性
float的破坏性主要是指它会使父容器的高度塌陷,也就是父元素在高度计算的时候会忽略浮动的元素
完全理解float之“不完全脱离文档流”

文章插图
可以看到图中名为的元素高度为0 。这个特性也正是它能够实现文字环绕的原因,但是由于后来float被大量应用到页面布局之中,所以这个我们不得不想办法清除浮动,这个在下文会有提到 。
2. float和:脱离文档流
虽然在我们常常看到描述float和的时候,都陈伟脱离文档流,但是实际上并不完全相同:
在脱离文档流方面,正如它的名字一般 , 是绝对脱离,设置了该属性的元素,将完全独立在文档流之外,不会对其他的元素产生任何影响 , 就举上面文字环绕的例子来说,如果把img属性的float换成:属性的话,那么p元素以及上面的文字都会顶到图片的位置上,就像这样:
完全理解float之“不完全脱离文档流”

文章插图
而对于float我们之前已经提出,float只是脱离了文档流的dom空间但是还占据着文字空间(这两个名词不知道是否已经有更标准的词语出现 , 在这里只是个人用法,见谅)
高度塌陷
float和都能引起父元素的高度塌陷,同样地,由于是完全脱离文档流,所以这种情况的高度塌陷是没办法清除的;float引起的高度塌陷则是可清除的 , 我们常说的清除浮动就是指清除float带来的高度塌陷问题,在下文会有提到 。
在两列布局中的使用
float和都被广泛用于两列布局之中,由于完全脱离,可以做到精准的定位,但是不利于设计两列之间的联动变化;float属性可以保留一些相互影响,但是要非常小心传递来的问题,比如clear的不当使用会导致左右布局异常联动,在后面讲清除浮动时会专门讲解 。而且在使用浮动布局的时候,要注意某些情况下要交换浮动左右浮动元素的声明次序 。
3. float和:-block横向排列
首先,使用float和-block都能使li横向排列 。但是,使用float可以选择排列的方向,而只有一种方向;
第二是在单纯排列图片的时候,如果图片大小不是完全一致的,那么使用这两个属性都能完成比较合适的排列:
完全理解float之“不完全脱离文档流”

文章插图
但是如果图片大小不等高,float的脱离文档流特性导致排列的某些图片会被挤到下一行 , 导致垂直方向无法对齐,如下:
完全理解float之“不完全脱离文档流”

文章插图
而如果使用:-block则可以保证垂直方向的对齐:
完全理解float之“不完全脱离文档流”

文章插图
所以如果是要保证垂直对齐的情况下,使用:-block会比较合适
float和-block这两个属性有一个很经常用到的地方就是横向导航 。导航中一般是单行对齐,而且除了图片之外还有文字,这时候如果采用:-block,必须要考虑:-block属性带来的空白间隙问题(这个问题可以自行查找,本文中不赘述) , 此时使用float:left更为合适一些 。
4.关于清除浮动清除浮动的方式
前文中提到float属性会引起父容器高度塌陷的问题,因此我们需要清除浮动 。
在阅读这块内容之前 , 请先了解css中的BFC(这个问题可以自行查找,本文中不赘述),在此基础上 , 我认为清除浮动,根据原理来划分 , 分为两类:
利用clear属性清除浮动
利用bfc原理包容浮动
首先介绍第一类,利用clear原理清除浮动,如果大家有过经验都知道,通常利用clear属性清除浮动的方式有两种:
这两种方式只是写法上有所不同,通过伪类清除可以让代码比较简洁,并且符合语义化的原则(其实就是可以少写无意义的空标签)现在比较流行的框架或者其他各大框架中,通常使用一下代码来清除:
.clearfix:before,.clearfix:after{display: table;content: " ";}.clearfix:after{clear: both;}.clearfix{zoom:1;} //ie 6 7
完全理解float之“不完全脱离文档流”

文章插图
其实这里 起清除浮动的作用 的是只是
.clearfix:after{content: " ";clear: both;}
至于和after中的:table;是为了防止子元素垂直方向上的边距折叠 , 也就是通常说的子元素-top会被转移到父元素的问题(为防止篇幅过长这个问题也不在此解释,如果有需要可以私信回答) 。
所以以上的效果就相当于在父元素最后插入一个子元素 , 并且设置clear:both属性,这是现在最通用的办法,但是其实并无是完美无缺的
clear使用不当的例子
(这里为什么用了大号呢,因为这个问题很重要!很重要!很重要?。?
举一个之前项目中碰到的一种情况,为了方便大家理解,在这里把模型简化,代码如下:
float*{padding: 0;margin:0;}.div1{float: left;width: 100px;height: 100px;background-color: lightpink;}.div2{margin-left:100px;background-color: lightgreen;}这是div1这是一个浮动的标题
这段代码是一个非常简单的左右两列布局 , 在右边内部有个浮动的标题,于是在后面跟上一个清 除浮动的子元素 (这里采用空标签只是为了在研究问题的时候排除伪类元素的干扰),但是存在一个问题: 右边的div2会自动适应div1的高度,或者说清除浮动的容器会有高度  , 我们可以在f12中直接改变左边div1的高度,可以看到右边的高度也随之改变 。
完全理解float之“不完全脱离文档流”

文章插图
这种情况有很多方法可以处理 , 比如让div2形成一个bfc容器,但是很少看到有文章讲到问题的根源,我查了很久,最后发现问题是源于clear这个属性上设计:
clear:
Thiswhich sides of an 's box(es) may not beto anbox. The 'clear'does nottheor in other block.
clear:both
that the topedge of the box be below theouter edge of any right- and left- boxes thatfromin the
以上是w3c文档上关于clear和clear:both的描述,大概有以下两个重点:
其实这个很好理解,我们之所以能够使用clear解决float引起的父元素塌陷问题,其实就是因为加了clear的空标签或者是那么伪类元素 , 把top值设置在了浮动元素的边缘下方,从而能够撑起父元素 。
所以最后我们就知道上面的问题出在哪里了:clear是清除某侧或者两侧的所有浮动,结合上面那个例子来看,其实是有两处浮动的,第一是左侧的div1,第二是在div2内部有个浮动的标题,我们的目的是要清除内部的浮动,但是因为clear本身的定义 , 就把两个浮动都清除了,也就是把加了clear属性的标签top值设置了浮动元素的边缘下方,所以,那个块将会和左侧等高(实质应是设置了clear空标签的高度为0并且top刚好在div的下方) 。
总结
上面的一段说的有点拗口,不知道大家有没有理解,不过可以拿例子去跑一下,应该就很容易理解了 。
既然问题找到了,那相应的解决方案也就出来了:
左侧使用布局避开这个问题
给右侧div2添加:auito形成bfc,从而隔离clear的作用范围
【完全理解float之“不完全脱离文档流”】现在回到清除浮动的问题主线,关于使用bfc包含浮动的情况 , 了解了bfc特点后我们就知道bfc的内部是会计算浮动元素的高度的,所以直接给浮动元素父元素加上:auto或者其他可以构成bfc的属性即可 。