1、什么是clear属性
clear: none | left | right | b
none:默认值,左右浮动来就来。
left:左侧抗浮动。
right:右侧抗浮动。
both:两侧抗浮动。
假设容器宽度足够宽,有10个
- 元素,设置了如下CSS代码:
-
li { width: 20px; height: 20px; margin: 5px; float: left; } li:nth-of-type(3) { clear: both; }
最后显示如下图所示
原因在于,clear属性是让自身不能和前面的浮动元素相邻,注意这里“前面的”3个字,也就是clear属性对“后面的”浮动元素是不闻不问的,因此才2行显示而非3行。
2、成事不足败事有余的clear
clear属性只有块级元素才有效的,而::after等伪元素默认都是内联水平,这就是借助伪元素清除浮动影响时需要设置display属性值的原因.clear:after { content: ''; display: table; // 也可以是'block',或者是'list-item' clear: both; }
如下图的清除浮动方法
<div class="father"> <img src="me.jpg"> <div class="animal"> 小猫1,小猫2, <div class="clear"></div> 小猫3,小猫4,小猫3,小猫4,小猫5,小猫6,小狗1,小狗2,小狗3,小狗4,小狗5,小狗6 </div> </div>
由于clear:both的作用本质是让自己不和float元素在一行显示,并不是真正意义上的清除浮动,因此float元素一些不好的特性依然存在,于是,会有类似下面的现象。
(1)如果clear:both元素前面的元素就是float元素,则margin-top负值即使设成-9999px,也不见任何效果。
(2)clear:both后面的元素依旧可能会发生文字环绕的现象。举个例子,如下HTML和CSS:<div class="father"> <img src="zxx.jpg"> 我是帅哥,好巧啊,我也是帅哥,原来看这本书的人都是帅哥~ </div> <div>虽然你很帅,但是我对你不感兴趣。</div> .father:after { content: ''; display: table; clear: both; } .father img { float:left; width: 60px; height: 64px; } .father + div { margin-top: -2px; }
虽然.father父元素的最后设置了clear:both来阻止浮动对后面元素的影响,但是最后结果错位依然发生了,如图6-17所示
由此可见,clear:both只能在一定程度上消除浮动的影响,要想完美地去除浮动元素的影响,还需要使用其他CSS声明。
3、 BFC的定义
BFC全称为block formatting context,中文为“块级格式化上下文”。相对应的还有IFC,也就是inline formatting context,中文为“内联格式化上下”。
如果一个元素具有BFC,内部子元素再怎么翻江倒海、翻云覆雨,都不会影响外部的元素。所以,BFC元素是不可能发生margin重叠的,因为margin重叠是会影响外面的元素的;BFC元素也可以用来清除浮动的影响,因为如果不清除,子元素浮动则父元素高度塌陷,必然会影响后面元素布局和定位,这显然有违BFC元素的子元素不会影响外部元素的设定。
那什么时候会触发BFC呢?常见的情况如下:
(1)根元素;
(2)float的值不为none;
(3)overflow的值为auto、scroll或hidden;
(4)display的值为table-cell、table-caption和inline-block中的任何一个;
(5)position的值不为relative和static。
换言之,只要元素符合上面任意一个条件,就无须使用clear:both属性去清除浮动的影响了。
4、BFC与流体布局<div class="father"> <img src="me.jpg"> <p class="animal">小猫1,小猫2,...</p> </div> img { float: left; } .animal { overflow: hidden; }
本来animal的内容显然受到了设置了float属性值的图片的影响而被环绕了。此时如果我们给.animal元素设置具有BFC特性的属性,如overflow:hidden。则根据BFC的表现原则,具有BFC特性的元素的子元素不会受外部元素影响,也不会影响外部元素。于是,这里的.animal元素为了不和浮动元素产生任何交集,顺着浮动边缘形成自己的封闭上下文,如图6-19所示(垂直虚线为辅助示意)
普通流体元素在设置了overflow:hidden后,会自动填满容器中除了浮动元素以外的剩余空间,形成自适应布局效果,而且这种自适应布局要比纯流体自适应更加智能。比方说,我们让图片的尺寸变小或变大,右侧自适应内容无须更改任何样式代码,都可以自动填满剩余的空间。例如,我们把图片的宽度从60px改成30px,结果如图6-20所示
如果想要保持合适的间距,那也很简单,如果元素是左浮动,则浮动元素可以设置margin-right成透明border-right或padding-right;又或者右侧BFC元素设置成透明border-left或者padding-left,但不包括margin-left,因为如果想要使用margin-left,则其值必须是浮动元素的宽度加间隙的大小,就变成动态不可控的了,无法大规模复用。
和基于纯流体特性实现的两栏或多栏自适应布局相比,基于BFC特性的自适应布局有如下优点:
(1)自适应内容由于封闭而更健壮,容错性更强。比方说,内部设置clear:both不会与float元素相互干扰而导致错位,也就不会发生类似于图6-22所示的问题。
(2)自适应内容自动填满浮动以外区域,无须关心浮动元素宽度,可以整站大规模应用。比方说,抽象几个通用的布局类名.left { float: left; } .right { float: right; } .bfc { overflow: hidden; }
任何BFC元素和float元素相遇的时候,都可以实现自动填充的自适应布局。但是,由于绝大多数的触发BFC的属性自身有一些古怪的特性,所以,实际操作的时候,能兼顾流体特性和BFC特性来实现无敌自适应布局的属性并不多。下面我们一个一个来看,每个CSS属性选一个代表来进行说明。
(1)float:left。浮动元素本身BFC化,然而浮动元素有破坏性和包裹性,失去了元素本身的流体自适应性,因此,无法用来实现自动填满容器的自适应布局。
2)position:absolute。这个脱离文档流有些严重。
(3)overflow:hidden。这个超棒!不像浮动和绝对定位,玩得有点儿过。其本身还是一个很普通的元素,因此,块状元素的流体特性保存得相当完好,附上BFC的独立区域特性,可谓如虎添翼、宇宙无敌!而且overflow:hidden的BFC特性从IE7浏览器开始就支持,兼容性也很不错。唯一的问题就是容器盒子外的元素可能会被隐藏掉,一定程度上限制了这种特性的大规模使用。不过,溢出隐藏的交互场景比例不算很高,所以它还是可以作为常用BFC布局属性使用的。
(4)display:inline-block。这是CSS世界最伟大的声明之一,但是用在这里,就有些捉襟见肘了。display:inline-block会让元素尺寸包裹收缩,完全就不是我们想要的block水平的流动特性。只能是一声叹息舍弃掉!然而,峰回路转,世事难料。大家应该知道,IE6和IE7浏览器下,block水平的元素设置display:inline-block元素还是block水平,也就是还是会自适应容器的可用宽度显示。于是,对于IE6和IE7浏览器,我们会阴差阳错得到一个比overflow:hidden更强大的声明,既BFC特性加身,又流体特性保留。
(5)display:table-cell。其让元素表现得像单元格一样,IE8及以上版本浏览器才支持。跟display:inline-block一样,它会跟随内部元素的宽度显示,看样子也是不合适的命。但是,单元格有一个非常神奇的特性,就是宽度值设置得再大,实际宽度也不会超过表格容器的宽度。第3章单元格一柱擎天的例子利用的就是这种特性,如图6-23所示
因此,如果我们把display:table-cell这个BFC元素宽度设置得很大,比方说3000px,那其实就跟block水平元素自动适应容器空间效果一模一样了,除非你的容器宽度超过3000px。实际上,一般Web页面不会有3000px宽的模块,所以,要是实在不放心,设个9999px好了.float-left { float: left; } .bfc-content { display: table-cell; width: 9999px; }
还是有两点制约,一是需要IE8及以上版本的浏览器;二是应付连续英文字符换行有些吃力。
(6)display:table-row。对width无感,无法自适应剩余容器空间。
(7)display:table-caption。此属性一无是处。
所以总结下来BFC能自适应布局的:
1)overflow:auto/hidden,适用于IE7及以上版本浏览器;
2)display:inline-block,适用于IE6和IE7;
3)display:table-cell,适用于IE8及以上版本浏览器。
提炼出两套IE7及以上版本浏览器适配的自适应解决方案
1)借助overflow属性,如下:.lbf-content { overflow: hidden;}
(2)融合display:table-cell和display:inline-block,如下:
.lbf-content { display: table-cell; width: 9999px; /* 如果不需要兼容IE7,下面样式可以省略 */ *display: inline-block; *width: auto; }
这两种基于BFC的自适应方案均支持无限嵌套,因此,多栏自适应可以通过嵌套方式实现。这两种方案均有一点不足,前者如果子元素要定位到父元素的外面可能会被隐藏,后者无法直接让连续英文字符换行。
关于display:table-cell元素内连续英文字符无法换行的问题,事实上是可以解决的,就是使用类似下面的CSS代码:.word-break { display: table; width: 100%; table-layout: fixed; word-break: break-all; }