IE的layout布局

我们那知道浏览器有bug,而且Windows上的lE的bug 似乎比太多数浏览器都多。IE/Win的表现与其他浏览器不同的原因之一是,显示引擎使用一个称为布局(layout)的内部概念。因为布均是一个专门针对显示引擎内部工作方式的概念,所以一般悄况下不需要了解它。但是,布局问题是许多IE/Win显示bug的根源,所以理解这个概念以及它如何影响CSS是有捂助的。

haslayout 是Windows Internet Explorer渲染引擎的一个内部组成部分。在Internet Explorer中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组织内容。为了调节这两个不同的概念,渲染引擎采用了 hasLayout 的属性,属性值可以为true或false。当一个元素的 hasLayout 属性值为true时,我们说这个元素有一个布局(layout)。

当一个元素有一个布局时,它负责对自己和可能的子孙元素进行尺寸计算和定位。简单来说,这意味着这个元素需要花更多的代价来维护自身和里面的内容,而不是依赖于祖先元素来完成这些工作。因此,一些元素默认会有一个布局。当我们说一个元素"拥有layout"或"得到layout",或者说一个元素"has layout" 的时候,我们的意思是指它的微软专有属性 hasLayout 被设为了 true 。一个"layout元素"可以是一个默认就拥有 layout 的元素或者是一个通过设置某些 CSS 属性得到 layout 的元素。如果某个HTML元素拥有 haslayout 属性,那么这个元素的 haslayout 的值一定只有 true,haslayout 为只读属性 一旦被触发,就不可逆转。通过 IE Developer Toolbar 可以查看 IE 下 HTML 元素是否拥有haslayout,在 IE Developer Toolbar 下,拥有 haslayout 的元素,通常显示为"haslayout = -1"。

负责组织自身内容的元素将默认有一个布局,主要包括以下元素(不完全列表):

1 * body and html
2 * table, tr, th, td
3 * img
4 * hr
5 * input, button, file, select, textarea, fieldset
6 * marquee
7 * frameset, frame, iframe
8 * objects, applets, embed

对于并非所有的元素都默认有布局,微软给出的主要原因是"性能和简洁"。如果所有的元素都默认有布局,会对性能和内存使用上产生有害的影响。

大部分的 IE 显示错误,都可以通过激发元素的 haslayout 属性来修正。可以通过设置 css 尺寸属性(width/height)等来激发元素的 haslayout,使其"拥有布局"。如下所示,通过设置以下 css 属性即可。

1 display: inline-block
2 height: (任何值除了auto)
3 float: (left 或 right)
4 positionabsolute
5 width: (任何值除了auto)
6 * writing-mode: tb-rl
7 * zoom: (除 normal 外任意值)

Internet Explorer 7 还有一些额外的属性(不完全列表):

1 min-height: (任意值)
2 max-height: (除 none 外任意值)
3 min-width: (任意值)
4 max-width: (除 none 外任意值)
5 overflow: (除 visible 外任意值)
6 * overflow-x: (除 visible 外任意值)
7 * overflow-y: (除 visible 外任意值)
8 positionfixed

其中 overflow-x 和 overflow-y 是 css3 盒模型中的属性,目前还未被浏览器广泛支持。

对于内联元素(默认即为内联的元素,如 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 影响,并且大小可以根据内容自适应调整。这也可以解释为什么单单在 IE/Win 中内联元素可以包含块级元素而少出问题,因为在别的浏览器中 display: inline 就是内联,不像 IE/Win 一旦内联元素拥有 layout 还会变成 inline-block。

当网页在 IE 中有异常表现时,可以尝试激发 haslayout 来看看是不是问题所在。常用的方法是给某元素 css 设定 zoom:1 。使用 zoom:1 是因为大多数情况下,它能在不影响现有环境的条件下激发元素的 haslayout。而一旦问题消失,那基本上就可以判断是 haslayout 的原因。然后就可以通过设定相应的 css 属性来对这个问题进行修正了。建议首先要考虑的是设定元素的 width/height 属性,其次再考虑其他属性。

对 IE6 及更早版本来说,常用的方法被称为霍莉破解(Holly hack),即设定这个元素的高度为 1% (height:1%;)。需要注意的是,当这个元素的 overflow 属性被设置为 visible 时,这个方法就失效了。或者使用 IE 的条件注释。

对 IE7 来说,最好的方法时设置元素的最小高度为 0 (min-height:0;)。

haslayout 问题引起的常见 bug:

  • IE6 及更低版本的双空白边浮动 bug。bug 修复: display:inline;
  • IE5-6/win 的 3 像素偏移 bug。bug 修复: _height:1%;
  • E6 的躲躲猫(peek-a-boo) bug。bug 修复: _height:1%;

常见bug及其修复方法

CSS 开发人员最重要的技能之一是发现常见浏览器bug的能力。通过了解导致这些bug 的各种元索,可以在它们造成问题之前发现并且修复它们。

双空白边浮动bug:最常见且最容易发现的bug 之一是IE6和更低版本中的双空白边浮动bug。顾名思义,这个Windows bug使任何浮动元素上的空白边加倍。

这个bug 很容易修复,将元素的display 属性设置为inline 就行了.因为元素是浮动的,将display 属性设置为inline 实际上不会影响显示方式。但是,这似乎会阻止Windows 上的IE6和更低版本将所有空白地加倍。这是一个非常容易发现和修复的bug : 每当对具有水平空白边的元素进行浮动时,都应该很自然地将display 属性设置为inline。

3像素文本偏移bug:另一个非常常见的I E 5-61Win bug 是3像素文本偏移bug。当文本与二个浮动元示相邻时,这个bug 就会表现出来。例如,假设将-个元素向左浮动,并且不希望相邻段落中的文本围绕浮动元素。你可能会在段落上应用一个左空白边,其宽度等于浮动元素的宽度:

1 .myFloat { floatleftwidth200px; }
2 p { margin-left200px; }

如果这么做,在文本和浮动元素之间就会出现一个莫名其妙的3像素间隙。

修复这个bug 需要双管齐下。首先,给包含文本的元素设置任意的高度。这会迫使元素拥有布局,这在表面上会消除文本偏移。因为Windows 上的IE6和更低版本将height作为min-height那样对待,所以设置一个小的高度并不会影响元素在这些浏览器巾的实际尺寸。但是,这会影响其他浏览器,所以要使用Holly招数对除了Windows 上的IE6 和更低版本之外的所有其他浏览器隐藏这个规则,

1 /* Hide from IE5-Mac. Only IE-Win sees this. \*/
2 * html p { height1%; }
3 /* End hide from IE5/Mac */

不幸的是,这么做会导致另一个问题。正如在前面学到的,拥有布局的元素被限制为矩形的,并且出现在浮动元索的旁边而不是它们的下面。添加200像素的空白边实际上会在IE 5-6/Win 中在浮动元素和段落之间产生200像素的间隙。为了边免这个问隙,需要将IE 5-6/Win 上的空白边重新设置为零:

1 /* Hide from IE5-Mac. Only IE-Win sees this. \*/
2 * html p { height1%margin-left0; }
3 /* End hide from IE5/Mac */

文本偏移被修复了,但是现在另一个3像亲间隙出现了,这一次是在浮动元素上。为了去掉这个问隙,需要在浮动元素上设置一个负值的3像素右空白边:

1 /* Hide from IE5-Mac. Only IE-Win sees this. \*/
2 * html p { height1%margin-left0; }
3 * html .myFloat { margin-right-3px; }
4 /* End hide from IE5/Mac */

如果浮动元素是除了图像之外的任何其他东西,那么这个问题己经修复了。但是,如果浮动元旦在是图像,那么还有放后一个问题需要解决。 IE 5.x/Win在图像的左右都添加3像亲的间隙。而IE6不改变图像的空白边。因此,需要用另一个招术在IE 5.x/Win 上去掉3 像素的问隙:

1 /* Hide from IE5-Mac. Only IE-Win sees this. \*/
2 * html p { height1%margin-left0; }
3 * html img.myFloat { margin0 -3px; ma\rgin: 0; }
4 /* End hide from IE5/Mac */

这会解决问题,但是采用的方式很难看而且太复杂。因此,如果可能的话,最好将这些规则分别放进单独的浏览器特定的样式表中。如果这样做,用于Windows 上的lE 5.x的样式表如下:

1 p { height1%margin-left0; }
2 img.myFloat { margin0 -3px; }

用于IE 6的样式表如下:

1 p { height1%margin-left0; }
2 img.myFloat { margin0; }

IE 6躲躲猫bug:另一个奇怪而且很烦人的 bug 是IE6 的躲躲猫(peek-a-boo) bug,之所以起这个名称是因为在某些条件下文本看起来消失了,只有在前新装载页面时才再度出现。出现这个bug 的条件是:一个浮动元素后面跟着一些非浮动元素,然后是一个清理元素,所有这些元素都包含在一个设置了背景颜色或阅像的父元束中。如果清理元素碰到了浮动元素,那么中间的作浮动元素看起来消失了,隐藏到了父元素的背景颜色或图像后面,只有在刷新页面时才重新出现。

我要讨论的段后一个主要浏览器bug涉及相对定位容器中的绝对定位元素。在前面的章节中你学到将绝对定位的元素嵌套在相对容器中是多么有用。但是,IE 6和更低版本在使用这种技术时有许多bug。

这些bug 的原因在于相对定位的元素没有获得IE/Win 的内部hasLayout 属性。因此,它们不创建新的定位上下文,所有绝对定位元素相对于窗口进行定位。

为了使Windows 上的IE 6和更低版本的表现正确。需要迫使相对应位的容器拥有布局。一种方法是在容器上显式地设置width 和height。但是,常常希望在不知道容器的width 和height的况下,或者在需要这些属性保持灵活的情况下使用这种技术。

可以使用Holly 招数为容器提供一个的高度。这会让容器拥有布局。但是因为IE 6和更低版本中的元素会不正确地扩展以适应它们的内容,所以设置小的高度不会影响实际高度。

1 /* Hides from IE-Mac \*/
2 * html .container { height1%; }
3 /* End hide from IE-Mac */

不要抱怨 IE

IE 并不足惟一一种有bug 的浏览器,所以你可能会奇怪我为什么只关注IE bug。 不必担心,我找并不是专门和微软过不去,这么做是有理由的。

首先, IE 目前占有最大的浏览器市场份额。因为有许多人在使用IE,IE bug 往往很快被发现而且很好地记录下来。当在IE中发现一个重大的CSS bug时,许多开发人员会尝试寻找修复方法或解决方案。由于IE的流行程度,被记录并修复的IE bug比其他任何浏览器都要多。

另一个主要问题是开发的节奏。Firefox、Safari和Opera等浏器不断地进行更新,新版本以非常高的频率出现。 bug 几乎一经发现就被修复了,并且发布浏览器的新版本.因此,现在讨论的任何Firefox或Safari bug 可能已经被下一个修订版修复了。

如此高的开发节奏确实很棒,但是也有自己的问题。开发人员要应付的浏览器版本不是两三个,而是20或30个。你无法确定用户是否使用最新的版本,这使测试变得极其困难。另一方面,IE差不多5年没有发布主要修订版了。因此,bug 有更多的时间可以暴露出来,开发人员也有更强的寻找修复方法的动力。

幸运的是,IE 7承诺将成为更符合标准的浏览器。许多著名的IE bug 已经被解决,而且对高级CSS 2.1 选择器(比如子选择器和属性选择器)的支持也在增加。与所有浏览器一样,新的bug也会出现,IE 7远不是完美的。但是,人们越快地升级到IE 7和Firefox 等现代浏览器,IE 5.0等老式浏览器就会越快地退役。在这个过渡时期,可以考虑使用Dean Edwards 的IE 7 补丁。这是一系列JavaScript 文件,它们使IE 5-6/Win 能够接近IE 7的水平.这包括改进的选择器实现和许多bug 修复。

posted @ 2018-02-24 15:33  前端极客  阅读(1301)  评论(0编辑  收藏  举报