在本章中,你将学习:
- 如何跟踪 bug 。
- 神秘的 hasLayout 属性。
- 最常见的浏览器 bug 及其修复方法。
9.1 bug 捕捉


#box {
margin: 10px;
padding: 1px;
background-color: #d5d5d5;
}
p {
margin: 20px;
background-color: #6699ff;
}
*******空白边叠加的大多数问题可以通过添加透明的边框或1像素的填充来修复。*******
9.3 拥有布局
我们都知道浏览器有 bug ,而且 Windows 上的 IE 的 bug 似乎比大多数浏览器都多。IE/Win 的表现与其他浏览器不同的原因之一是,显示引擎使用一个称为布局(layout)的内部概念。因为布局是一个专门针对显示引擎内部工作方式的概念,所以一般情况下不需要了解它。但是,布局问题是许多 IE/Win 显示 bug 的根源,所以理解这个概念以及它如何影响 CSS 是有帮助的。
标准模式下: IE6 ,IE7 受 hasLayout 影响,IE8,IE9 不受 hasLayout 影响
怪异模式下: IE6, IE7,IE8,IE9 都受 hasLayout 影响
9.3.1 什么是布局
Windows 上的 IE 使用布局的概念来控制元素的尺寸和定位。那些称为拥有布局 (have layout) 的元素复杂本身极其子元素的尺寸和定位。如果一个元素没有拥有布局,那么它的尺寸和位置由最近的拥有布局的祖先元素控制。
IE 显示引擎利用布局概念减少它的处理开销。在理想情况下,所有元素都控制自己的尺寸和定位。但是,这会在IE中导致很大的性能问题。因此,IE/Win 开发团队决定只将布局应用于实际需要它的那些元素,这样就可以充分地减少性能开销。
在默认情况下拥有布局的元素包括:
- body
- 标准模型中的 html
- table
- tr、td
- img
- hr
- input、select、textarea、button
- iframe、embed、object、applet
- marquee
- position: absolute
- float: left 或 right
- display: inline-block
- width: 任何值
- height: 任何值
- zoom: 任何值 (Microsoft 属性 -- 不能通过校验)
- writing-mode: tb-tl (Microsoft 属性 -- 不能通过检验)
9.3.2 布局有什么效果?

这会导致浮动布局的各种问题。更糟糕的是,许多人使用 IE 作为主浏览器,他们会错误地认为这才是正确的表现,在其他浏览器以不同方式处理浮动元素时,他们反而会迷惑不解。
另一个问题涉及拥有布局的元素如何确定自己的尺寸。如果元素的内容变得比元素本身大,那么期望内容流出到元素外。但是,在 Windows 上的 IE6 和更低版本中,拥有布局的元素会错误地扩展以便适应内容的尺寸 (见图 9-6)。
标准模式下: IE6会扩展,IE7,IE8, IE9 不会
怪异模式下: IE6,7,8 会扩展 IE9 不会
********这意味着 IE/Win 中的 width 实际上更像是 min-width 。这种行为也是在 IE/Win 中许多浮动布局被破坏的原因。当浮动框的内容错误地迫使框的宽度增加时,框对于可以空间来说太大了,因此下降到其他浮动元素下面。*********
其他问题包括:
- 拥有布局的元素不进行收缩。
- 布局元素对浮动进行自动清理。
- 相对定位的元素不获得布局。
- 在拥有布局的元素之间空白边不叠加。
- 在不拥有布局的块级链接上,单击区域只覆盖文本。
9.4 常见 bug 及其修复方法
9.4.1 双空白边浮动 bug
最常见且最容易发现的 bug 之一是 IE6 和更低版本中的双空白边浮动 bug 。顾名思义,这个 Windows bug 使任何浮动元素上的空白边加倍 (见图 9-7)。
这个 bug 很容易修复,将元素的 display 属性设置为 inline 就行了。因为元素是浮动的,将 display 属性设置为 inline 实际上不会影响显示方式。但是,这似乎会阻止 Windows 上的 IE 6 和更低版本将所有空白边加倍。这是一个非常容易发现和修复的 bug : 每当对具有水平空白边的元素进行浮动时候,都应该很自然地将 display 属性设置为 inline 。
9.4.2 3像素文本偏移 bug
另一个非常常见的 IE 5-6/Win bug 是3像素文本偏移 bug 。当文本与一个浮动元素相邻时,这个 bug 就会表现出来。例如,假设将一个元素向左浮动,并且不希望相邻段落中的文本围绕浮动元素。你可能会在段落上应用一个左空白边,其宽度等于浮动元素的宽度:
.myFloat {
float: left;
width: 200px;
}
p {
margin-left: 200px;
}
如果这么做,在文本和浮动元素之间就会出现一个莫名奇妙的3像素间隙 (见图 9-8)。
修复这个 bug 需要双管齐下。首先,给包含文本的元素设置任意的高度。这会迫使元素拥有布局,这在表面上会消除文本偏移。因为 Windows 上的 IE6 和更低版本将 height 作为 min-height 那样对待,所以设置一个小的高度并不会影响元素在这些浏览器中的实际尺寸。但是,这会影响其他浏览器,所以要使用 Holly 招数对除了 Windows 上的 IE6 和更低版本之外的所有浏览器隐藏这个规则:
/* Hide from IE5-Mac .Only IE-Win sees this. \*/
* html p {
height: 1%;
}
/* End hide from IE5/Mac */
不幸的是,这么做会导致另一个问题。正如前面学到的,拥有布局的元素被限制为矩形的,并且出现在浮动元素的旁边而不是它们的下面。添加 200 像素的空白边实际上会在 IE5-6/Win 中在浮动元素和段落之间产生 200 像素的间隙。为了避免这个间隙,需要将 IE 5-6 /Win 上的空白边重新设置为零:
/* Hide from IE5-Mac . Only IE-Win sees this. \*/
* html p {
height: 1%;
margin-left: 0;
}
/* End hide from IE5-Mac. */
文本偏移被修复了,但是现在另一个 3像素间隙出现了,这一次是在浮动元素上。为了去掉这个间隙,需要在浮动元素上设置一个负值的3像素右空白边:
/* Hide from IE5-Mac . Only IE-Win sees this. \*/
* html p {
height: 1%;
margin-left: 0;
}
* html .myFloat {
margin-right: -3px;
}
/* End hide from IE5/Mac */
如果浮动元素是除了图像之外的任何其他东西,那么这个问题已经修复了。但是,如果浮动元素是图像,那么还有最后一个问题需要解决。IE 5.x/Win 在图像的左右都添加3像素的间隙,而 IE6 不改变图像的空白边。因此,需要用另一个招数只在 IE 5.x/Win 上去掉 3像素的间隙:
/* Hide from IE5-Mac. Only IE-Win sees this. \*/
* html p {
height: 1%;
margin-left: 0;
}
* html img.myFloat {
margin: 0 -3px;
ma\rgin: 0;
}
/* End hide form IE5/Mac */
9.4.3 IE6 重复字符 bug
另一个涉及浮动元素的奇怪的 bug 是 IE6 的重复字符 bug 。在某些条件下,一系列浮动元素的最后一个元素中的最后几个字符会在浮动元素下面重复出现,见图 9-9.
当在一系列浮动元素的第一个和最后一个元素之间有多个注释时,就会出现这个 bug 。前两个注释没有影响,但是后续的每个注释会导致两个字符重复出现。所以,三个注释会导致两个重复字符,四个注释会导致四个重复字符,五个注释会导致六个重复字符。
奇怪的是,这个 bug 似乎与前面的 3 像素文本偏移 bug 相关。为了修复这个 bug ,可以通过设置负值的右空白边从最后一个浮动元素上去掉 3 像素,或者使容器扩大3像素。但是,这两种方法可能在 IE7 中造成问题,IE7中可能没有这个 bug 。因此,避免这个 bug 最容易、最安全的方法是从 HTML 代码中删除注释。
9.4.4 IE6 躲躲猫 bug
另一个奇怪而且烦人的 bug 是 IE6 的躲躲猫 (peek-a-boo) bug,之所以起这个名称是因为在某些条件下文本看起来消失了,只有在重新装载页面时才再度出现。出现这个 bug 的条件是 :一个浮动元素后面跟着一些非浮动元素,然后是一个清理元素,所有这些元素都包含在一个设置了背景颜色或图像的父元素中。如果清理元素碰到了浮动元素,那么中间的非浮动元素看起来消失了,隐藏到了父元素的背景颜色或图像后面,只有在刷新页面时才重新出现 (见图 9-10)。
幸运的是,有许多方法可以解决这个 bug 。最容易的方法可能是去掉父元素上的背景颜色或图像。但是,这常常是不可行的。另一个方法是避免清理元素与浮动元素接触。如果容器元素应用了特定的尺寸,那么这个 bug 似乎就不会出现了。如果给容器指定行高,这个 bug 也不会出现。最后,将浮动元素和容器元素的 position 属性设置为 relative 也会减轻这个问题。
9.4.5 相对容器中的绝对定位
我要讨论的最后一个主要浏览器 bug 涉及相对定位容器中的绝对定位元素。在前面的章节中你学到将绝对定位的元素嵌套在相对容器中是多么有用。但是,IE6 和更低版本在使用这种技术时有许多 bug 。
这些 bug 的原因在于相对定位的元素没有获得 IE/Win 的内部 hasLayout 属性。因此,它们不创建新的定位上下文,所有绝对定位元素相对于视口进行定位(见图 9-11)。
为了使 Windows 上的 IE6 和更低版本的表现正确,需要迫使相对定位的容器拥有布局。一种方法是在容器上显示地设置 width 和 height 。但是,常常希望在不知道容器的 width 和 height 的情况下,或者在需要这些属性保持灵活的情况下使用这种技术。
可以使用 Holly 招数为容器提供一个任意的高度。这回让容器拥有布局,但是因为 IE6 和更低版本中的元素会不正确地扩展以适应它们的内容,所以设置小的高度不会影响实际高度。
/* Hides from IE-Mac \*/
* html .container {
height: 1%;
}
/* End hide from IE-Mac */