转: https://www.jianshu.com/p/07eb19957991css
CSS里浮动float是个概念比较暧昧的属性,撸主最先对浮动float的认识是基于布局的,认为float元素就是用于:“让block元素无视float元素,让inline元素让流水同样围绕着float元素”来实现浮动布局。如今想一想,当初真是图样图森破。html
其实这个属性撸主一直是比较模糊的,感受似懂非懂。本着和本身死磕的精神,在参考了许多大神的博文后,将个人理解整理概括在本文中,但愿能能够帮助到你。固然撸主水平有限,若有错误敬请指出。前端
如下是网上大神关于float的优秀文章:编程
CSS float浮动的深刻研究、详解及拓展(一)前端工程师
那些年咱们一块儿清除过的浮动wordpress
传统如C++,Java等编程语言一个API可能只能对应作一件事,即便有了模板和泛型编程,一般也只能作某一类事。但CSS是门至关灵活的语言。某个CSS属性被用于的场景,可能会彻底违背当初创造该CSS属性的本意。在CSS的世界里,想实现某个效果,会有不少方法。那究竟选择哪一种方法呢?有不少判断标准,如重绘,如回流,如极简主义。撸主也有一个不成熟的判断标准就是:根据该CSS属性被创造时的本意,该用哪一个属性就用哪一个属性。
那浮动float的本意是什么呢?是:让文字像流水同样环绕浮动元素。布局
怎样才能实现该效果呢?用 包裹性 和 高度欺骗学习
例1:首先来看浮动float的包裹性,所谓一图胜千言:
相关代码很是简单:
<div style="border:4px solid blue;">
<img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;float:left;">
<img src="img/25/2.jpg" />
</div>
所谓包裹性一目了然。block元素不指定width的话,默认是100%,一旦让该div浮动起来,马上会像inline元素同样产生包裹性,宽度会跟随内容自适应。(这也是一般float元素须要手动指定width的缘由)
再加上一个div的话,效果以下:
<div style="border:4px solid blue;">
<img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;float:left;">
<img src="img/25/2.jpg" />
</div>
<div style="border:4px solid green;">
<img src="img/25/3.jpg" />
</div>
效果很是近似于display:inline-block。但相比之下,浮动能设定为左浮和右浮,但display:inline-block都是从左到右排列的。(还有些细微差异,两个display:inline-block间会有空隙,但两个float间没有。这不是本篇的主题,暂时略过)
(首先声明:实际上是CSS层级在起做用,但CSS层级适合单独写一篇,内容实在太多,不适合在这里展开,就理解为高度欺骗吧)
例1中浮动float被设在了外围div上,所以高度欺骗性没体现出来。如今给内层img元素设定float。所谓一图胜千言:
<div style="border:4px solid blue;">
<img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;">
<img style="border:4px solid yellow;float:left;" src="img/25/2.jpg" />
</div>
和例子1惟一的区别就是:将外层div的float移到内层img中。这下高度欺骗性体现出来了。例1中给外层div加上浮动,所以外层div会有包裹性,其内容是img图片,因此能够看到红色边框包裹着img。
例2中外层div没有了浮动,所以红色边框宽度默认是100%全屏。其内容img因为加上了float,使得该img具备了欺骗性。float给img施了个障眼法,让该img的inline-height高度塌陷为0了。这样外层div计算高度时,认为img的高度为0,至关于div的content的高度为0,所以红色边框看起来是一条直线。
但请注意障眼法毕竟是障眼法,并非真的让img的高度塌陷为0了,能够看到上图中img的黄色边框仍是有正常高度的。若是给div里加点文字,效果以下:
能够看到,外层div在没有手动设定height的前提下,其高度是由内部content的最大高度决定的,因为img的float使得img具备高度塌陷的欺骗性,让div误觉得img的line-height为0,所以div的高度就是文字的匿名inline-box的inline-height。
所以浮动并非让元素的高度塌陷了,而是让元素具备高度塌陷的欺骗性。骗谁?骗别人!但骗不了本身,元素自身仍是有高度的(见上图的黄框)。
回过头再看看浮动float的本意:让文字像流水同样环绕图片。重要的事情多看几遍...给div设定一个width:200px,并加点文字吧:
这就是浮动元素的本意。该效果是很难被其余CSS属性等价地模拟的。
但就像开头说的,CSS强大的灵活性使得不少CSS属性被用于了创造者都没想到的场景。以float为例,就被普遍用于了布局。是好是坏呢?不知道!西红柿臭鸡蛋先别急着扔。既然撸主不知道,还废话什么?先看看float布局的问题。渣浪微博改版前的好友列表用浮动布局,效果以下:
<ul>
<li style="width:138px;margin:0 10px;text-align: center;float:left;">
<div><img src="img/25/1.jpg" />尼古拉斯.旺财</div>
</li>
<li style="width:138px;margin:0 10px;text-align: center;float:left;">
<div><img src="img/25/2.jpg" />功夫熊猫</div>
</li>
<li style="width:138px;margin:0 10px;text-align: center;float:left;">
<div><img src="img/25/3.jpg" />月野兔</div>
</li>
<li style="width:138px;margin:0 10px;text-align: center;float:left;">
<div><img src="img/25/4.jpg" />猫女郎</div>
</li>
</ul>
每一个li都设为浮动和定宽,实现了水平布局。但若是好友再长点呢?效果以下:
错行啦!常见的修正方案是手动设定一个高度,让文字固定显示一行,用裁掉超行文字的代价以免错行问题。在撸主看来这就是让CSS属性用于不合原意处的局限性。设固定高度是OK,但若是哪天设计师以为姓名须要显示两行呢,那固定高度就须要从新计算从新变。若是设计师以为须要拓宽俄罗斯市场,姓名要显示三行呢?再把固定高度改大点。若是将来Boss脑壳一拍,咦,能不能高度自适应呢?由姓名最大高度的好友来决定每行的高度。你是否是会有准备一下简历的冲动?
固然现实没这么夸张,高度自适应是个烂大街的技术,将浮动float改为 display:inline-block 就好了,效果以下:
代码只需将上面float:left;替换成display: inline-block;,没对齐只需给li加上个vertical-align: top;(上面提到过,相比float,display:inline-block中间会有空隙,眼神好的能够从图中就能看出来,解决方案不是本篇的主题,能够问度娘)。这下高度自适应了,每行的高度都是以名字最长的高度为准。
回过头看用float来水平布局。是好是坏呢?好处是上手简单,随便什么程度的CSSer都能搞定。坏处是有时须要定高难以自适应。而display:inline-block;属性但是根正苗红的水平布局的属性,能够用其替代float。让float尽可能多的干其本职工做:让文字像流水通常环绕浮动元素。因此撸主不知道答案。或许也根本没有正确答案,不停的推翻原有的认识和想法人才能进步。
PS:用浮动布局还有个坏处就是IE6下可能会有问题。但在IE6横行时期,撸主经验尚浅,如今项目里早已明确弃用IE6,撸主也懒得挖坟验证了。
这个相对比较简单了。用clear便可。稍微要注意的是,clear是仅做用于当前元素,例如元素A是浮动元素,靠左显示。元素B是block元素紧跟在A后面。此时要清除浮动,是在B上设clear:left。你在A上设clear:right是没有用的,由于A的右边没有浮动元素。
但真这么简单吗?图样图森破。
先明确一个概念,用clear确实能达到咱们指望的清除浮动的效果,这点没异议。但深刻点看,到底是清除了什么样的浮动呢?一图胜千言:
代码:(给页脚加上clear:left)
<div style="border:4px solid blue;">
<div style="width:200px;border:4px solid red;float:left;">
我是浮动元素1
</div>
<div style="width:200px;border:4px solid yellow;float:left;">
我是浮动元素2
</div>
</div>
<div style="border:4px solid gray;clear:left;">我是页脚</div>
由于浮动元素的高度欺骗性,致使外层div失去了高度(蓝色边框成了一条线)。为了让页脚显示到浮动元素下面,对页脚应用了clear:left。这是常规作法,没有任何新奇之处。可是外层div的高度仍旧处于塌陷状态,咱们脑海真真正指望的清除浮动后的样子难道不是下面这样吗?
闭合浮动的实现方法不少,常见的是最后增长一个清除浮动的子元素:
<div style="border:4px solid blue;">
<div style="width:200px;border:4px solid red;float:left;">
我是浮动元素1
</div>
<div style="width:200px;border:4px solid yellow;float:left;">
我是浮动元素2
</div>
<div style="clear:both;"></div> //加上空白div节点来闭合浮动
</div>
<div style="border:4px solid gray;">我是页脚</div>
缺点是会增长一个DOM节点。(话说当初撸主不知道在哪里看到这个作法时,做者并未讲这么作的缘由,致使撸主不明白明明页脚加一个clear属性就能搞定的事,为什么要大动干戈加一个DOM节点)
方法二:一样能够在最后增长一个清除浮动的br:将上面代码中<div style=”clear:both;”></div>
替换成<br clear=”all” />
便可。语义上比空的div标签稍微好一点,但一样会增长一个DOM节点。
方法三:父元素设置 overflow:hidden(若是你还要兼顾IE6的话,加上*zoom:1;来触发hasLayout)
<div style="border:4px solid blue;overflow:hidden;">
<div style="width:200px;border:4px solid red;float:left;">
我是浮动元素1
</div>
<div style="width:200px;border:4px solid yellow;float:left;">
我是浮动元素2
</div>
</div>
<div style="border:4px solid gray;">我是页脚</div>
这看起来很奇怪。由于子元素的浮动的高度欺骗,致使父元素误认为content高度为0(即蓝色边框为一条线),因此父元素设成overflow:hidden溢出隐藏的话,直觉上应该子元素因为溢出致使不显示才对,即整个页面只显示页脚。但实际效果,父元素设成overflow:hidden溢出隐藏后,居然神奇地出现了闭合浮动的效果(蓝色边框正确得到了高度)。这是怎么回事呢?靠的是BFC,但BFC提及来又是很长一篇,先略过。你能够先简单地这么理解:浏览器厂商认为要让超出边框部分能够被修剪掉,那么前提就是父元素要正确得到高度,即父元素不能被欺骗致使高度塌陷。浏览器正确得到子元素的高度后给父元素从新设置高度。虽然权威解释确定是BFC,但撸主这样理解了好久...
方法四:同上面将父元素设置 的overflow:hidden改为auto,不赘述
方法五:父元素也设成float。这样确实实现了闭合浮动,但页脚将上移,因此页脚仍旧须要clear:left。还有个缺点是因为浮动的包裹性,你肯定父元素真的设成float对页面布局不会产生影响吗?
方法六:父元素设置display:table。效果OK,页脚也不须要设clear:left,但父元素的盒子模型被改变了,请先确认下这样的改动对页面布局不会产生影响吗?
方法七:用:after伪元素,思路是用:after元素在div后面插入一个隐藏文本”.”,隐藏文本用clear来实现闭合浮动:
.clearfix:after { clear: both; content: "."; //你头能够改为其余任意文本如“abc” display: block; height: 0; //高度为0且hidden让该文本完全隐藏 visibility: hidden; } .clearfix { *zoom: 1; }
<div style="border:4px solid blue;" class="clearfix">
<div style="width:200px; border:4px solid red; float:left;">
我是浮动元素1
</div>
<div style="width:200px; border:4px solid yellow; float:left;">
我是浮动元素2
</div>
</div>
<div style="border:4px solid gray;">我是页脚</div>
这个方法很不错,就是相比上面的方法,理解起来稍微有一点点难度。但也仅增长一点点而已。
第一篇文章啰嗦几句。其实本文开头连接的几篇博文写的比我好,为什么我要写这篇博文?是我自信能比大神们写的更好吗?固然不是。之因此写技术博文是由于这是一个很是好的学习总结的方式。就在写以前我仍旧觉得已经很是了解float了,但真要提笔写,又发现本身在很是多的细节方面仍是只知其一;不知其二。只有真正静下心来,边思考边作demo验证边总结,才能将本身的知识总结成一篇博文。
技术博文不是散文,必须条理清晰,结构严谨,经得起推敲,不能满嘴跑火车,不然就误人子弟了。之前看优秀的文章时,偶尔会看到做者吐槽:这段话足足写了一下午。这篇文章写了三天三夜。看着文章字数又很少,最多10分钟就看完了,但若是你没有真正提笔写过,你可能体会不到期间的困难。
做为一个起步很是晚的前端工程师(I know…I late to the Party.)我只能死磕本身。