第9章 bug 和 bug 修复

来源:互联网 发布:录音转换文字软件 编辑:程序博客网 时间:2024/06/07 03:17

在本章中,你将学习:

  • 如何跟踪 bug 。
  • 神秘的 hasLayout 属性。
  • 最常见的浏览器 bug 及其修复方法。

9.1 bug 捕捉

2.空白边叠加的问题

空白边叠加 (见第2章) 是另一个如果误解就会导致许多麻烦的 CSS 特性。请考虑 div 元素内嵌段落的简单示例:
<div id="box">
<p>This paragraph has a 20px margin.</p>
</div>
div 框设置了 10 像素的空白边,段落设置了 20 像素的空白边:
#box {
margin: 10px;
background-color: #d5d5d5;
}
p {
margin: 20px;
background-color: #6699ff;
}
你会自然地认为产生的样式会像图 9-2 那样,在段落和 div 之间有 20 像素的空白边,在 div 外边围绕着 10 像素的空白边。

但是,产生的样式实际上像图 9-3 这样。

这里发生了两个情况。首先,段落的20像素顶空白边和底空白边与 div 的10像素空白边叠加,形成一个单一的20像素垂直空白边。其次,这些空白边不是被 div 包围,而是突出到 div 的顶部和底部的外边。出现这种情况是由于具有块级子元素的元素计算其高度的方式造成的。
如果元素没有垂直边框或填充,那么它的高度就是它包含的子元素的顶部和底部边框边缘之间的距离。因此,包含的子元素的顶部和底部空白边就突出到容器元素的外边。但是,有一个简单的解决方案。通过添加一个垂直边框或填充,空白边就不再叠加了,而且元素的高度就是它包含的子元素的顶部和底部空白边边缘之间的距离。
为了让前面的示例看起来像图 9-2 这样,只需在 div 周围添加填充或边框:

#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
布局概念是 Windows 上的 IE 特有的,而且它不是 CSS 属性。尽管某些 CSS 属性会使元素拥有布局,但是在 CSS 中无法显示地设置布局。可以使用 JavaScript 函数 hasLayout 查看一个元素是否拥有布局。如果元素拥有布局,这个函数就返回 true;否则返回 false。hasLayout 是一个只读属性,所以无法使用 JavaScript 进行设置。
设置以下 CSS 属性会自动地使元素拥有布局:
  • position: absolute
  • float: left 或 right
  • display: inline-block
  • width: 任何值
  • height: 任何值
  • zoom: 任何值 (Microsoft 属性 -- 不能通过校验)
  • writing-mode: tb-tl (Microsoft 属性 -- 不能通过检验)

9.3.2 布局有什么效果?

布局是许多 IE/Win 显示 bug 的根源。例如,如果一个文本段落靠着一个浮动元素,那么期望文本围绕这个元素。但是,在 Windows 上的 IE6 和更低版本中,如果段落拥有布局 (例如,由于设置了高度),那么它就被限制为矩形,因此阻止文本围绕浮动元素 (见图 9-5)。

这会导致浮动布局的各种问题。更糟糕的是,许多人使用 IE 作为主浏览器,他们会错误地认为这才是正确的表现,在其他浏览器以不同方式处理浮动元素时,他们反而会迷惑不解。

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


标准模式下: IE6会扩展,IE7,IE8, IE9 不会

怪异模式下: IE6,7,8 会扩展 IE9 不会

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

其他问题包括:

  • 拥有布局的元素不进行收缩。
  • 布局元素对浮动进行自动清理。
  • 相对定位的元素不获得布局。
  • 在拥有布局的元素之间空白边不叠加。
  • 在不拥有布局的块级链接上,单击区域只覆盖文本。

9.4 常见 bug 及其修复方法

CSS 开发人员最重要的技能之一是发现常见浏览器 bug 的能力。通过了解导致这些 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 */


原创粉丝点击