一直以来都在寻找清除浮动的方法,之前找到两种,第一种就是加空标签,第二种在元素尾部使用伪元素,但是这两种方法都会dom树中产生无意义的标签,今天找到第三种方法:
首先说一下zoom
这个属性一般不为人知,甚至有些CSS手册中都查询不到。
其实Zoom属性是IE浏览器的专有属性,Firefox等浏览器不支持。它可以设置或检索对象的缩放比例。除此之外,它还有其他一些小作用,比如触发ie的hasLayout属性,清除浮动、清除margin的重叠等。
Zoom的使用方法:
zoom : normal | number
normal : 默认值。使用对象的实际尺寸
number : 百分数 | 无符号浮点实数。浮点实数值为1.0或百分数为100%时相当于此属性的 normal 值 用白话讲解就是zoom:后面的数字即放大的倍数,可以是数值,也可以是百分比。如:zoom:1,zoom:120%。 而这个属性只要在IE中才起作用,所以很少用到它的实际用途,而最经常用到作用是清除浮动等,如:
.border{
border:1px solid #CCC;
padding:2px;
overflow:hidden;
_zoom:1;
}
_zoom是CSS hack中专对IE6起作用的部分。IE6浏览器会执行zoom:1表示对象的缩放比例,但这里
overflow:hidden;和_zoom:1;是连起来用的,作用是清除border内部浮动。
同理,还可以使用同样方法清除margin属性在IE浏览器中的重叠问题。
下面的内容来自
http://www.zhangxinxu.com/wordpress/?p=621
一、前面的一些YY
首先,不知道您注意到没有,标题“清除浮动”加了个引号。我最近在想,这个所谓的“清除浮动”的是否准确。人有从众的心理,尤其在我们这个集体主义文化的社会,从众并不是一个消极的标签,在亚洲集体主义文化里(例如日本),其象征着忍耐,自我控制,以及成熟,但是,有时会延续一些不准确的观点,还记得小学“两个铁球同时落地”的故事吗。
我这里要说一些个人的,很情感化的东西,非常欢迎反驳。我在国外的技术上也经常见到”clear float”一词,翻译过来就是“清除浮动”,我入行较浅,所以我只能臆想,是不是“清除浮动”确实表示了那个意思,于是就广泛使用,越是使用广泛越不容易发现其中的不严谨之处。
我最近思考“清除浮动”的一些东西,发现,“清除浮动”这个说法越想越觉得不准确。准确的说法应该是“清除浮动造成的影响”,真正的“清除浮动”是什么呢,float:none;
这才是“清除浮动”的字面意思。当然,也有可能是“清除浮动”就是个简称,意思就是“清除浮动造成的影响”,只是叫了顺口,大家也都这么称呼了,大家其实都心知肚明。希望自己是想多了。
YY结束,进入本文正题,一些思考性的内容,讲讲我对overflow与zoom可以清除浮动造成影响的原因的理解,都是些浅薄的认识,希望真正理解的人能够指点纠正,大大欢迎反驳,发表您自己的观点。
二、元素的包裹性
“包裹”这个名词常出现在JavaScript中,尤其jQuery之类的js库,很形象的一个词。昨天我看到这么句很有启发性的话:“视觉化思考能以独特而有效的方式,让你的心有更大的空间来解决问题。”启发性在于,这里的“视觉化思考”改为其他一些名词,例如“情感化思考”,“形象化思考”等同样受用。也就是在思考问题的时候融入一些很主观的非逻辑性的思考有助于有更广阔的空间来解决问题。
一提到“包裹”一词,我想到了就是白细胞吞噬细菌(形象化思考 – 联想),以及温暖及安心(情感化思考)。这因人遗传、成长等因素相关。为什么我要讲这些看似无关主题的东西,因为下面我要将的很多东西就是自己的感觉,“我觉得它就是这个样子的”,很多主观的东西。
CSS中,有很多的属性一提到我就会想到“包裹”这个词,像“浮动”,“绝对定位”,“inline-block”,“overflow”,“zoom”,就这些,没有其他了。//zxx:这里的overflow特指overflow:hidden/scroll/auto属性,不包括overflow:visible;
对于浮动,我在“CSS float浮动的深入研究、详解及拓展(一)”一文中花了一大段讲浮动的包裹性,一个div,默认宽度100%显示,一旦有了浮动属性(none除外),其宽度包裹与内部的元素,浮动的包裹性显而易见。
对于absolute绝对定位,我在“absolute绝对定位的非绝对定位用法”一文中也提到过其包裹性,相信有经验的同行们应该都知道absolute元素的这个特性,即absolute元素(如果没有设置width值),其宽度自适应于内部元素,也正是这个原因,absolute属性常在jQuery插件中用来做宽度计算。所以,absolute元素也是具有包裹性的。
对于inline-block,这个可以说是包裹的祖宗了,无论是float还是absolute的包裹性都是向inline-block靠齐的,神奇而伟大的inline-block元素,它的故事可以写成一本书了,打住,不多说。
对于,浮动(float),绝对定位(position:absolute)以及inline-block的包裹性我称之为“主动包裹”,其标签宽度会收缩至内部元素大小;而overflow与zoom,我称之为“被动包裹”。
对于overflow的包裹性其实不难理解,例如一个div里面仅有个浮动元素(一张美女图片),那么这个div高度会塌陷,现在这个div要应用overflow:hidden;
属性,想想看,既然div高度塌陷,那么div里面的这个图片就应该在div的外部,按照overflow:hidden的功能,这个图片应该直接-“咔”-一声截掉不显示的,但是这可以吗,显然不行,怎么办,只能去包裹这个浮动的美女图片,于是设置了overflow:hidden属性的div有了高度,同时把浮动的图片封在了里面。您可能会想到IE下的overflow好像没有这么回事,事实上是这样的,IE6/7对overflow属性的理解有误,说白了是IE6/7的一个bug,IE8已经修复这个问题,也就是说IE8下overflow:hidden可以清除浮动造成的影响,您有兴趣可以自己测试一下。
(多谢dony的提醒)修正为:
IE6对overflow属性的理解有误,说白了是IE6的一个bug,IE7开始已经修复这个问题,也就是说IE7/IE8下overflow:hidden可以清除浮动造成的影响,您有兴趣可以自己测试一下。
对于zoom的包裹性…恩…还是先简单介绍下这个zoom属性吧,也很简单,就是比例缩放,跟CSS3中transform:scale;作用一样(表现有些许差异),举个例子吧,看看zoom的表现,如下代码:
<div > <img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" border="0" /> </div>
结果如下图所示(由于zoom为IE私有属性,故对比IE和Firefox可见效果,左Firefox,右IE6):
可见在IE6下,zoom:2;
让图片,包括外部的div放大两倍显示,IE7下也是如此,但是IE8下却有差异,在IE8(标准)下,zoom所放大的仅仅是内部元素,自身并没有放大,如下图:
您可以狠狠地点击这里:zoom功能效果demo //zxx:这是第一次展示新demo页面,是不是比白板的要舒服些啊,O(∩_∩)O
同样是overflow美女图片的例子,现在zoom是要让元素放大或是缩小,我们可以这样想,要是没有zoom等属性,IE6和IE7下,浮动属性的图片的父div的高度塌陷,就是个痿蛋0;再假设现在有个div标签上有个zoom:2;
的样式来放大父标签及里面图片2倍,肯定是从父标签开始拉伸缩放的,但是如果父标签是个塌陷高度,无论怎么拉伸,其高度依旧是那个0,也就是说拉伸根本就没有效果,这显然也不应该,于是“被动的包裹”似乎成为了必要。
对于IE8,则zoom属性无“包裹性”,正如上面IE8下截图显示,IE8 zoom放大的是内部元素,父标签不缩放,于是父标签即使是个痿蛋0,其与内部元素的缩放一点关系也没有,也就没有的包裹的必要。所以IE6/7 zoom有包裹性,IE8没有。
有人可能会质疑,明明就是zoom让IE haslayout,于是…… 我要问的是,你清楚的看得见这个haslayout吗?为什么haslayout可以清除浮动造成的影响?不急,下面我会解释为什么不用haslayout这个东西。
三、“包裹”与“清除浮动”
清除浮动造成的影响的方法有两大类,一类就是clear:both/left/right;
清除,另外一类就是本文要讨论的“包裹”清除。
我在上部分提到的这些“包裹性”元素都可以清除浮动造成的影响,我们可以一个一个的来测试:
float:left
测试代码如下:
<div > <img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" /> </div>
结果如下图:
可见含有浮动属性图片的父标签的高度并没有塌陷。您可以狠狠地点击这里:float清除浮动造成的影响demo
position:absolute
测试代码如下:
<div > <img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" /> </div>
结果与上图一模一样,不重复显示了。其他话就不多说了,您可以狠狠地点击这里:absolute清除浮动造成的影响demo
display:inline-block
测试代码如下:
<span > <img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" /> </span>
结果还是与浮动的效果图一样,节省篇幅,不重复显示了。其他话就不多说了,您可以狠狠地点击这里:inline-block清除浮动造成的影响demo
overflow:hidden
测试代码如下:
<div > <img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" /> </div>
结果如下图:
上图效果在Firefox,chrome,Safari以及IE8下会见到,至于IE6/7,我前面提过了,其对overflow:hidden的理解有误,另当别论。overflow:hidden属于“被动包裹”,故宽度没有包裹属性,依旧原延展性显示,高度包裹。
您可以狠狠地点击这里:overflow清除浮动造成的影响demo
zoom:1
zoom:1指的就是原大小显示,测试代码如下:
<div > <img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" /> </div>
结果在IE6/7下与overflow:hidden在Firefox等现代浏览器下的效果一样,见下图:
您可以狠狠地点击这里:zoom清除浮动造成的影响demo
从上面一系列的测试可以看到,“包裹”确实可以解决浮动造成的影响,或者说用“包裹”来解释为什么这些CSS属性可以修复浮动元素父标签高度塌陷的问题是可行的。
四、“包裹” – haslayout – 清除浮动造成的影响
就目前而言,就主流而言,在IE下清除浮动造成的影响是使用haslayout来解释的,确实很说的通,我也不否认其存在性。我很长一段时间也是使用haslayout来解释一些IE下的问题(清除浮动效果就是其一),但是我一旦想到Firefox等浏览器并没有haslayout的概念,为何其一些属性也能抑制浮动产生的影响呢?那么Firefox的浏览器抑制浮动副作用的原理是什么呢?有没有一个更好的概念解释所有这些浏览器下一些CSS熟悉抑制浮动副作用的原因呢?好,于是我就想到了“包裹”这个概念来解释,我发现使用“包裹”解释抑制浮动影响比haslayout更概括更有前途。
我觉得haslayout就是个要淘汰的东西,这是IE8说的。几举个例子,我们都知道IE6/7下设置width值会使元素haslayout,能够清除浮动造成的影响,例如设置100%;
,这非常解释的通,但是IE8下呢?抱歉,IE8下设置100%根本就不鸟你,无法清除浮动的坏影响、我不清楚是IE8淡化了haslayout这个概念,还是width值与haslayout根本就不搭边?总之,在IE8下,使用haslayout解释一些现象(例如抑制浮动副作用)已经很吃力了,但是,使用“包裹性”来解释没有一点问题,要知道IE8下overflow:hidden可以清除浮动产生的影响,是因为overflow:hidden让IE有haslayout吗?我想应该不是吧,因为overflow:hidden具有“包裹性”。还有IE8下width值无法抑制浮动副作用,又是什么原因呢?因为width属性无“包裹性”可言,所以自然不会抑制浮动副作用。还有IE8的zoom为何不能清除浮动高度塌陷问题?因为IE8下的的zoom没有“包裹性”。
所以,对于IE下zoom清除浮动造成的高度塌陷问题,我使用了“包裹”来解释,而没有使用不知会不会淘汰的haslayout这个概念来解释。
五、最后的总结
本文首先以YY的方式将“清除浮动”这个概念用“清除浮动造成的影响”这个更准确的方式表述,然后列举一些具有包裹性的CSS属性,再通过实例证明这些具有包裹性的元素都具有抑制浮动副作用的作用,来证明使用“包裹性”这个概念可以解释为何有些元素可以消除浮动使父标签高度塌陷的问题。最后解释了为何不使用haslayout来解释清除浮动造成的影响。