php斯芬克斯,斯芬克斯之迷——ie私有属性haslayout的困扰

就象神话中的斯芬克斯一样,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

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
更多右列宽度自适应布局的方法: http://www.cssass.com/blog/index.php/2008/31.html

IE下的haslayout会引发很多问题:

IE 很多常见的浮动 bug 。

元素本身对一些基本属性的异常处理问题。

容器和其子孙之间的边距重叠(margin collapsing)问题。

使用列表时遇到的诸多问题。

背景图像的定位偏差问题。

使用脚本时遇到的浏览器之间处理不一致的问题。

她经常让我们困惑不堪。

但是只要逐步认识她,重视她。经常怀疑,怀疑自己的怀疑。我们就能慢慢摸清她的谜题,了解问题的本质。

这篇文章发布于 2009年03月21号,星期六,07:02,归类于 CSS2, 浏览器与兼容。您可以跟踪这篇文章的评论通过 RSS 2.0 feed。

您可以留下评论,或者从您的站点trackback。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值