10.3 IE的hasLayout
在 IE 浏览器中,一个元素要么自己对自身的内容进行组织和计算尺寸,要么依赖于包含块来组织内容和计算尺寸。
为了协调这两种方式的矛盾,IE 浏览器的渲染引擎使用了一个私有属性 hasLayout,它是一个布尔型变量,取值为 true 或 false。 当一个元素的 hasLayout 属性取值为 true 时,就说这个元素“拥有布局”。
hasLayout是一个只读属性,无法通过 Javascript 进行设置,但可以通过 Javascript 读取它的值。如:
object.currentStyle.hasLayout;
在IE中,使用 hasLayout 来控制元素的尺寸和定位:当一个元素拥有布局时,由它自己来控制自身及后代元素的定位和尺寸;否则,将由最近拥有布局的祖先元素来控制。
由于浏览器要花费更多的代价来处理拥有布局的元素,为了提高性能,IE 设计者只让一部分元素默认拥有布局。这些元素包括:
- html、body
- table、tr、td
- img
- hr
- input、select、teatarea、button、fieldset
- iframe、embed、object、applet
- marquee
除了 IE 默认拥有布局的元素外,Web 开发者还可以使用特定的 CSS 属性使元素拥有布局,也被称作“使元素触发布局”。设置以下任一CSS属性,会自动使元素拥有布局:
- position: absolute
- float: left或right
- display: inline-block
- width: 除auto外的任何值
- height: 除auto外的任何值
- zoom: 除normal外的任何值(Microsoft属性,不能通过检测)
- writing-mode: tb-rl(Microsoft属性,不能通过检测)
另外,在IE7中,设置以下任一CSS属性,也会使元素触发布局:
- position: fixed
- overflow: hidden或scroll或auto
- min-width: 任何值
- max-width: 除 none 外的任何值
- min-height: 任何值
- max-height: 除 none 外的任何值
特别注意的是,IE 8 使用全新的渲染引擎,并抛弃 hasLayout。因此,在实际开发中,只需针对 IE 8 以下的版本,为某些元素触发 hasLayout。
有经验的CSS开发人员都知道,hasLayout 可能是许多IE 问题的根源。一个典型例子,就是当一个元素内只包含浮动或绝对定的位元素时,会导致父元素的高度塌陷。在IE6或IE7中,为元素添加 zoom:1 就触发了haslayout,就可以修复高度塌陷的问题。
虽然 hasLayout 也会像 BFC 那样影响元素的尺寸和定位,但它却不是一套完整的标准。并且,默认情况下,只有部分元素拥有布局,这导致了 IE 下的诸多 Bug,触发布局的更大意义在于解决IE 下的一些Bug,而不是利用它的一些“副作用”来达到某些效果。