IE css bug的罪恶根源——hasLayout(布局)

由于各个浏览器的渲染CSS引擎不同,从而导致工程师们要写很多代码来解决很多兼容性的问题,在 css 不兼容上lE的 bug 比太多数浏览器都多。IE的与其他浏览器不同的原因之一是,IE的CSS渲染引擎使用一个称为布局(layout)的内部概念。很多的ie下的css bug都与其息息相关。所以理解这个概念以及它如何影响CSS是有捂助的。

什么是布局(layout)

“Layout”是一个 IE 的私有概念,IE 中使用布局概念来控制元素的尺寸和定位。那些称为拥有布局(have layout)的元素负责本身及其子元素的尺寸和定位。如果一个元素在没有拥有布局(layout),那么它的尺寸和位置由最近的拥有布局的祖先元素控制。

IE CSS渲染引擎利用布局概念减少它的处理开销。在理想悄况下,所有元素都控制自己的尺寸和定位。但是实际上当一个元素的hasLayout属性值为true时,它负责对自己和可能的子孙元素进行尺寸计算和定位。这意味着这个元素需要花更多的代价来维护自身和里面的内容。因此,IE开发团队决定只将布局应用于实际需要它的那些元素,这样就可以充分地减少性能开销。

触发方式

‘Layout’ 可以被某些 CSS property(特性)不可逆的触发,而某些 HTML 元素本身就具有 layout 。

默认拥有布局”layout”的元素

默认就具有”layout”的HTML元素:

  • body
  • 标准模式中的 html
  • table,tr, td,th
  • img
  • hr
  • input, select, textarea, button
  • iframe, embed, object, applet
  • marquee

一个元素得到 ”layout”,或者说一个元素拥有 layout 的时候,是指它的微软专有属性 hasLayout 为此被设为了 true 。不同于标准属性,也不像某些浏览器的私有 CSS 属性,layout 无法通过某一个 CSS 声明直接设定 。也就是说没有 layout 属性这么一个东西,元素要么借助一些 CSS 声明悄悄地获得 layout,或者也借助它们来取消 layout 属性。

能让一个元素获得 layout 的CSS属性

下面列出可以触发hasLayout的一些CSS属性值:

  1. position:absolute
  2. float:left or right
  3. display:inline-block;
  4. width|height: 除auto的所有值
  5. zoom: 除narmal和空值的所有值;
  6. writing-mode: tb-rl (Microsoft property—doesn’t validate)
  7. position: fixed,因为IE7支持position: fixed,所以也能开启hasLayout (在 IE 7 中)
  8. min-height|min-width:所有值(在 IE 7 中)
  9. max-width|max-height: 除none所有值,(在 IE 7 中)
  10. overflow|overflow-x|overflow-y: hidden|scroll|auto,(在 IE 7 中)

IE6(包括IE6) 以前的版本, 通过以上属性都可以触发 hasLayout ; 但在 IE6 和 IE7 的标准模式中的行内元素上却不行,设置 ‘display:inline-block’ 才可以。

能让一个元素撤销 layout 的CSS属性

可以给节点中增加hasLayout,也可以通过它们撤销 hasLayout ,如果给他属性添加 hasLayout 的话。

下面列出可以触发hasLayout的一些CSS属性值:

  1. position:static
  2. width|height:auto
  3. float:none
  4. zoom:narmal或者空值
  5. writing-mode:lr-t
  6. overflow|overflow-x|overflow-y: visible (在 IE 7 中)
  7. max-width|max-height :none(在 IE 7 中)

当设置了 display:inline-block 就设置了 haslayout = true 了,就会覆盖”block”或”inline”,haslayout 这个标志位也不会被重置为 false。

所以通过设置以上属性来触发 layout ,我们就同样可以通过它们来撤销 layout。

大家所熟识的IE是会触发 布局(layout)的,IE7只是对IE6出现的大量bug的修补版(本质上一样),所以IE7也会触发布局(layout)的。其实,在包括 IE6 及以后所有版本的混杂模式(这种混杂模式在渲染方面就相当于 IE 5.5)都是会触发布局(layout)

W3C组织在css2.1提出了 block formatting context 的概念,类似于IE的私有概念布局(layout),IE8貌似按照这个标签来的。而且创建 Block Formatting Context中跟能触layout的属性有重叠,导致表现会有差异,所以,解决他们的兼容性也是很有必要的~~详细情况的block formatting context

布局(layout)有什么效果?

布局是许多IE显示bug 的根源。例如, 如果一个文本段落靠近一个浮动元索,那么期望文本围绕这个元索。但是,在Windows 上的IE 6 和更低版本巾,如果段落拥有布局(例如,由于设置了高度).那么它就被限制为矩形,会阻止文本围绕浮动元素,如下:

<img src="/pic/html5jscss.jpg" alt="IE css bug的罪恶根源——hasLayout(布局)" alt="" style="float:left;">
<p style="height:1%"> 无浮动文字<br> 无浮动文字<br> 无浮动文字<br> 无浮动文字<br> 无浮动文字<br> 无浮动文字<br> 无浮动文字<br> 无浮动文字<br></p>

如上代码会在IE和非IE上会出现如下图情况:

IE css bug的罪恶根源——hasLayout(布局)

文本和浮动元素

期望文本围绕相邻的浮动元素,但是,在IE上,如果文本元素拥有布局,就会跟其他浏览器显示不同。

另-个问题涉及拥有布局的元素如何确定自己的大小,如果元素的内容变得比元素本身大,那么期望元素流出到元素外。但是,在IE 6 和更低版本中,拥有布局的元素会销误地扩展以便适应内容的尺寸,如下图所示

IE css bug的罪恶根源——hasLayout(布局)

IE6下拥有布局(layout)跟其他浏览器的不同

意味着IE6中的width 实际上更像min-width。 这种行为也是在IE中许多浮动布局被破坏的原因。当浮动框的内容错误地迫使框的宽度增加时,框对于可用空间来说太大了,因此下降到其他浮动元素在下面.

所以以下代码就能解决IE6不支持min-width属性的兼容方案:

.min-layout {
    _height:100px;
    min-height:100px
}
解决IE6中不支持min-width方案

IE6 识别_height:100px,因此它的高度是100px,前面说过,IE6内容超出时 div 的高度会随着内容的高度页变(自适应),IE7、Firefox、Opera、Chrome 可以识别 min-height:240px 和 支持min属性 ,所以就这样,很简单吧。

内联级别元素

对于内联元素,可以是默认即为内联的比如 span 元素,也可以是 display: inline 的元素。

  • width 和 height 只在 IE5.x 下和 IE6 或更新版本的 quirks 模式下触发 hasLayout 。而对于 IE6,如果浏览器运行于标准兼容模式下,内联元素会忽略 width 或 height 属性,所以设置 width 或 height 不能在此种情况下令该元素具有 layout。
  • zoom 总是可以触发 hasLayout,但是在 IE5.0 中不支持。

具有”layout” 的元素如果同时也 display: inline ,那么它的行为就和标准中所说的 inline-block 很类似了。在段落中和普通文字一样在水平方向和连续排列,受 vertical-align 影响,并且大小可以根据内容自适应调整。因为设置了display: inline的元素,触发了”layout”就相当于有布局的内联元素了。

所以要想在IE6、IE7中 ‘display:inline-block’ 特性,内联或者display: inline 的元素只需直接设置此特性值或同样使用 ‘zoom:1’ 即可。

布局(layout)引起的各种问题:

Layout 在显示盒模型时有着不同寻常而且难以预料的效果,而且有时甚至会牵连到他们的子元素。

一个元素是否具有”layout”可能会引发如下的一些问题:

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

看了上面我们也许知道了,引起这个BUG的原因就是因为:IE中的元素,自己没有触发 layout,而受最近触发了 layout 属性的的祖先元素或者兄弟元素影响,从而引起了这些BUG,一般解决方案就是在不影响其他浏览器的情况下设置能触发 layout 的CSS值。

因为IE是中国在用户数最大的浏览器(很多山寨浏览器内核都是IE内核,所以算上它们数字会更大),用的人多了,发现的bug也会多,再加上IE不像Firefox、Safari和chrome等浏器经常更新。 bug 一经发现就被修复了在下一个版本就会被修复。因此,讨论Safari bug Firefox、Safari和chrome等浏器是不实际的,这也是为啥网上讲IEBUG的文章一大堆,而其他现代浏览器的BUG缺几乎没有的原因吧。

掌握 IE布局(layout) 这个概念对 修复IE BUG是有很大帮助。所以我们不应该抱怨IE,这样即影响我们身体而且IE还是在那,也不要幻想哪天Firefox、Safari和chrome能把IE的份额全部吞并了(做梦~~)。我们要了解它,了解他才能真正解决它!问渠那得清如许?为有源头活水来。

最后说明此文章大部分是整理自:
此文参考自On Having Layout

本文源链接:http://www.html5jscss.com/ie-haslayout.html

转载请注明《IE css bug的罪恶根源——hasLayout(布局)》| html5jscss

评论关闭了.