就象神话中的斯芬克斯一样,ie的私有属性haslayout是个神秘且让人困惑的难缠东西,她只游荡于ie(这片沙漠)之下。
她无法使用css声明直接创建。即便是对于ie,她也不能说是一个实实在在存在的属性。
ie下的元素有些本身拥有haslayout(基本上是一些拥有内在尺寸的可置换元素),有些可以通过一些css属性可以触发产生。我们可以在ie developer toolbar上查看到到haslayout这个属性项,他的值是-1。这说明这个元素触发了layout。
详细haslayout资料:On having layout抄录
更详细资料:译文On having layout这篇文章本人还没怎么看,相信很多问题在这里都有解释
遇到斯芬克斯是件很麻烦的事情,她会给你提出很多怪怪的让人困惑的问题,更何况只要我们在ie沙漠中游荡的话,遇到的概率是非常高的。
遇到她,我们会有三种结果:
猜不出迷题的答案——我们会在迷失在困惑中;
猜错了迷题的答案——我们会误会很多东西;
猜对了迷题的答案——恭喜你,你就不用怕斯芬克斯这个丑婆娘了。
那让我们来猜一下她的几个比较困惑的问题吧。
斯芬克斯之迷1:是firefox错了?
*{padding:0;margin:0;}
.wrap{}
#left{float:left;color:red;}
#right{background:#ccc;margin-top:50px;}
left 在FF下,对right设置margin-top。结果不止right上方空出了50px;连left也一样空出了50px;是FF的解析有问题吗?
left是浮动元素,她脱离了文档流(注意,这是下一个斯芬克斯之迷),所以right的margin-top相对的是其上级wrap作用的。但我们只是对right设置margin-top。结果在FF下,怎么连left也“产生了margin-top”呢。对比ie和FF下的效果,是不是觉得IE下的解析会比较合理呢?
但是
别忘了影响margin-top/bottom的一个重要规则——margin塌陷(margin collapsing)。
在ff下就是产生了这么一个margin塌陷。导致wrap的”剥夺”了本属于子元素#right的margin-top值。
为了更加直观看出是否塌陷,可以給wrap添加一个背景:background:#000;
*{padding:0;margin:0;}
.wrap{background:#000}
#left{float:left;color:red;}
#right{background:#ccc;margin-top:50px;}
left 在FF下,对right设置margin-top。结果不止right上方空出了50px;连left也一样空出了50px;是FF的解析有问题吗?
在ff下wrap块的高度并没有被子元素right的margin-top撑开。反而自身拥有了50px的margin-top。
而浮动的left尽管脱离了文档流,但还是受其父级限制的(这跟absolute定位的元素层受限于其定义为relative的父级一样)。所以left还是包含在wrap之中,这样在ff下看起来left也拥有margin-top,而事实上是因为wrap高度不撑开的结果。
这么说,FF并没有错咯,那么IE下又是怎么避开margin塌陷的呢?
问题就出在浮动上面,在ie下,元素浮动将触发其haslayout。就是这个原因,使得在ie下意外(意外?)的就避开了margin塌陷。
haslayout差点让我们怀疑了我们的亲密伙伴firefox。
———-谜题之外———–
但是,margin塌陷往往不是我们想要的效果。那么我们需要怎么避开他呢?
可以看下这篇独立文章:如何解决麻烦的margin塌陷(margin collapsing)
斯芬克斯之迷2:在ie下,float元素不脱离文档流?
在前面的问题里,我们提到浮动元素时一直认为浮动元素脱离文档流。但是看一下下面这个现象:
ie下,float不脱离文档流?
*{padding:0;margin:0;}
.wrap{}
#left{float:left;color:red;}
#right{background:#ccc;width:500px;}
left ie下width:500px;触发了#right的layout,所以貌似ie下float并不会脱离文档流,
很多人都一直怀疑浮动元素脱离文档流的这种说法,就是因为ie下haslayout的经常出现。ie下,浮动的元素(left)牢牢的占着自己的位置。后面的block元素(right),只能跟随其后(请对比FF下的效果)。
没错,这又是haslayout在迷惑我们,这回除了left因为浮动触发了haslayout外,right也由于使用了width:500px也触发了haslayout,使得他考虑到了前面浮动的left元素。
如果把right的宽度去掉,或则把值改成auto。就能使ie下达到ff下一样的效果:后面的block元素会忽略前面浮动元素的存在,直接跑到浮动元素的z轴方向的下面(为什么是下面?因为浮动元素的Z值较正常的要高),而inline元素则环绕此浮动元素。
我们再看一个更加明了的demo:
haslayout影响浮动元素脱离文档流ie下。去除父级wrap的width:100%。对比效果。
由于父级使用width:100%.触发了haslayout。使得原本脱离文档流的浮动元素,又在其父级之内拥有了一席之地。
——-谜题之外——–
浮动有三个作用效果:
一是使得自身脱离文档流,使得父层不适应其高度,而后面的block元素也将忽略其“存在”,跑到浮动元素之下(可在block元素上加背景色查看);
二是使得后面的inline元素“顺流环绕”浮动元素。
三是浮动元素的尺寸,如果未定义的话,将按内部元素的尺寸来决定(而不是block元素默认的充满整行)。而且即便浮动元素本身是非可置换inline元素,她都可以定义width/height(还有margin也将算入尺寸计算)。
其实第一个效果往往不是我们所想要的。所以ie下的haslayout可以说正中我们下怀。那么FF下怎么让left元素不脱离文档流(看起来没有脱离)呢?
在上面的例子中,我们可以对right也使用浮动,或则在right加上overflow:hidden。
知道了这个原理,我们对于这个【右列宽度自适应】的布局(其实这是个左右布局均自适应的布局。一般来说我们会固定左列的宽度)就能很好理解了:
zoom:1针对IE系列触发haslayout.overflow:hidden针对FF。使得right不会忽视已经脱离文档流的浮动元素left。
二列,右列自适应宽度布局
*{padding:0;margin:0;}
.wrap{overflow:hidden;}
#left{float:left;color:red;}
#right{background:#ccc;zoom:1;overflow:hidden;}
left 更多右列宽度自适应布局的方法:/blog/index.php//31.html
IE下的haslayout会引发很多问题:
IE 很多常见的浮动 bug 。
元素本身对一些基本属性的异常处理问题。
容器和其子孙之间的边距重叠(margin collapsing)问题。
使用列表时遇到的诸多问题。
背景图像的定位偏差问题。
使用脚本时遇到的浏览器之间处理不一致的问题。
她经常让我们困惑不堪。
但是只要逐步认识她,重视她。经常怀疑,怀疑自己的怀疑。我们就能慢慢摸清她的谜题,了解问题的本质。
这篇文章发布于 03月21号,星期六,07:02,归类于 CSS2, 浏览器与兼容。您可以跟踪这篇文章的评论通过 RSS 2.0 feed。
您可以留下评论,或者从您的站点trackback。