我说hasLayout - 菜鸟篇

摘要:
这几天一直在学习前端开发的技能,好几次看到了hasLayout,却不知道它是什么东西,找了相关的问题看了一下,感觉还是挺深奥的,所以写下这篇文章,也算是方便后来人;
另外,个人能力有限,若有错误,还请大家不吝赐教 :)

谁需要关注hasLayout?
首先明确hasLayout的范畴:CSS && IE
看到这里,稍微有点经验的人,马上就能联想到CSS hack,如果能从这个角度来联想的话,也就能明白为什么要关注hasLayout、如何处理浏览器兼容性问题等。
PS:也许有些观众还不知道什么是CSS hack,那么我强烈建议不要再看下去了,因为你不知道我解释那么多,是因为什么、为了解决什么问题,更何况这问题对新手来说,难度实在太大。

hasLayout会导致什么兼容性问题?

1.IE5-6的3像素偏移

IE 很多常见的浮动 bug 。
元素本身对一些基本属性的异常处理问题。
容器和其子孙之间的边距重叠(margin collapsing)问题。
使用列表时遇到的诸多问题。
背景图像的定位偏差问题。
使用脚本时遇到的浏览器之间处理不一致的问题。
……

注:上面说的是我在网上摘抄的,我个人对这些问题没有做过测试,也不知道这属不属于hasLayout范畴,所以在此不进行演示,但在文章的后面我会举几个我觉得说得过去的例子。

 

为什么要引入hasLayout?
这是一个历史问题,我也没法去追究是哪个程序员引入的,当初为什么要这样设计,所以在此我整理一下网上的说法,方便大家记忆。
首先,网页元素(比如div)均有自己表现形式,比如说高度,对齐,但这种表现形式由谁来决定呢?
就好像我们军训,不招人喜欢的教官(IE)大吼一声:集合!
于是我们(HTML元素)赶紧排队,而排队的方式有两种:
1.我们自己(元素本身)决定站队的位置 - 这样虽然保证了成员的个性,但不便于整体协调,同时增加系统开销
2.队长(元素的容器)来决定我们站队的位置 - 由父元素来协调位置,显得更加高效而简洁,但这样就没法发挥各成员的个性,显得不够灵活

可以说,这两种站队(渲染)方式各有好处,但是队长需要知道,哪些成员是自己去站队,哪些成员需要自己去协调。
这么解决这个问题呢,答案就是hasLayout;
需要队长去协调位置的,成员的hasLayout属性为true,反之则为false;
再次提醒,hasLayout不是CSS属性,可以将hasLayout=true的情况理解为:has layout,即表示这个元素拥有布局,它需要去维护自己所包含元素的尺寸、大小、定位 - 能力越大,责任越大啊~~~

一些hasLayout特性
1.hasLayout仅针对IE浏览器
2.一个元素的hasLayout,一旦变为true,则不可逆转 - 就好像蜘蛛侠已经没法再变成一个普通人了~~
3.如果一个子孙元素也有布局,它会处理自身及其子孙元素的尺寸计算,但是它的定位是由它的父元素决定的。
4.默认hasLayout==true的元素有:body and html,table, tr, th, td,img,hr,input, button, file, select, textarea, fieldset,marquee,frameset, frame, iframe,objects, applets, embed - 记住常用的div、span是被协调的人,如果被协调错了,那么就试试让它自己去站队~

如何激发hasLayout?
通过对元素的CSS进行特定的设置来进行激发。由于规则有点繁杂,这里就不贴了,没啥意思,就贴一些主要的吧:
display: inline-block
height: (任何值除了auto)
float: (left 或 right)
position: absolute
width: (任何值除了auto)
zoom: (除 normal 外任意值)

对于内联元素(默认即为内联的元素,如 span,或 display:inline; 的元素),width 和 height 只在 IE5.x 下和 IE6 或更新版本的 quirks 模式下触发 hasLayout 。而对于IE6,如果浏览器运行于标准兼容模式下,内联元素会忽略 width 或 height 属性,所以设置 width 或 height不能在此种情况下令该元素具有 layout。

技巧:如何调试hasLayout

1.检测一个元素是否拥有 layout:举个例子,如果它的 id 是“eid”,那么只要 alert(eid.currentStyle.hasLayout) 即可检测它的状态。
2.常用的方法是给某元素 css 设定 zoom:1。使用 zoom:1 是因为大多数情况下,它能在不影响现有环境的条件下激发元素的 haslayout。而一旦问题消失,那基本上就可以判断是haslayout 的原因。注意:zoom是Internet Explorer专有的CSS属性,所以使用了会通不过CSS合法验证。

 

hasLayout测试例子

测试浏览器:IE6

1.一个不知道是不是bug的例子 - 之所以说不知道是不是bug,是因为IE和FF显示的效果一样

先看代码:

<style type="text/css">
  #left{color:red; float:left;width:200px;}
  #right{background:#ccc;}
</style>
</head>
<body>
   <div id="left"> float:left;width:200px;color:red; </div>
   <div id="right">background:#ccc;</div>
</body>

在IE6的显示效果:

image

若激发右层的hasLayout特性(即增加css属性zoom:1),让右层自己决定自身的尺寸计算,效果如下:
image

 

 

 

 

 

2.子层脱离父层

<div style="background:red;position: absolute; ">
绝对定位的层
</div>

image

本来div的宽度是要占满body的,但由于设置了绝对定位,宽度就由子元素来决定了。

<div style="background:red;position: absolute; ">
   <div>
      绝对定位的层
   </div>
</div>

image

可以看到子层由父层来协调尺寸和定位,所以效果改变不大,但如果激发子层的hasLayout特性呢?

<div style="background:red;position: absolute; ">
   <div style="zoom:1;">
      绝对定位的层
   </div>
</div>

image

就这样,子层忽略了父层,决定了自己本身的宽度,那么它的宽度应该怎么计算呢?

上面的例子,是占满了浏览器宽度(即body的宽度),现在再在外面套一个固定层试试:

<div style="width:300px; border:2px solid #00F;">
  <div style="position: absolute; background:red; border:1px solid #000">
    <div style="zoom:1;"> 绝对定位的层 </div>
  </div>
</div>

image

 

 

即最里层的宽度受限于最外层,最里层把中间层的宽度撑大(换个说法就是,中间层由自身的元素来决定宽度),另外,可以看出最外层的高度有问题(这应该是清除浮动范围的题,再次就不继续讨论了)

 

3.由position:relative引发的问题

<div style="border: 2px solid blue;position: relative; ">
   <div style="border: 2px solid red;float:left; ">
      <img style="border: 2px solid green; height:100px; position: relative; width:100px; " src="test.jpg">
   </div>
</div>

从代码上看,我们希望一个图片是绿色边框,接着紧密包着红色边框,最外层则是蓝色边框,但实际上呢:

image

如何解释呢?

1.图片采用的是相对定位,故依赖于父层(假设为F)计算其定位

2.F由于激发了hasLayout(通过float属性),加上IE6自身的bug,导致图片定位错误。而这个bug已在IE7中已经修复了:
image

解决的一个办法是激发最外层的hasLayout:

<div style="border: 2px solid blue;position: relative; zoom:1">
   <div style="border: 2px solid red;float:left; ">
      <img style="border: 2px solid green; height:100px; position: relative; width:100px; " src="test.jpg">
   </div>
</div>

image

 

 

 

总结

绕了那么多,最后觉得这篇文章依然是在讲述hasLayout的一些特点,以及尝试解决一些我们认为是的bug,但如果仔细地想想,显示的效果跟我们所期望的不同,我们可以认为这是浏览器的bug,也可以认为是我们不了解浏览器造成的,更糟糕的是,每个浏览器的脾气都不同,每个浏览器可以看做是存在bug,这才是我们头痛的主要原因。而bug是不可能完全消除的,甚至有时候我们表面上是为了消灭bug,到达我们所期望的效果,而实际上我们正好是在利用bug。
既然如此,我们何不回到初衷:让自己的代码能够兼容主流的浏览器(就好像写一份C代码,能放到windows下编译,也能够放到linux下编译)
而当前的浏览器,最大的问题依然是IE6,所以我们更应该把焦点放在它身上,了解它的脾气,更好地解决IE浏览器所引发的网页渲染问题。

转载于:https://www.cnblogs.com/wslcn/archive/2009/11/18/1605192.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值