在理想的环境中,编写正确的 CSS 会在支持 CSS 的每个浏览器中正常工作。不幸的是,我们并不是生活在理想的世界中,浏览器有不少 bug 和不一致的地方。为了创建能够在各种浏览器上显示相同样式的页面,CSS 开发人员需要发挥创造性。通过利用 bug 和未实现的 CSS ,开发人员能够选择性地对不同浏览器应用不同的规则。招数和过滤器是CSS开发人员的强大工具。但是,正因为功能强大,使用时更应该谨慎。了解各种常用招数以及它们的工作原理确实很重要,但是,了解在什么时候应该使用它们以及什么时候不应该使用也同样重要。
在本章中,你将学习:
- 招数和过滤器之间的差异。
- 好的过滤器和差的过滤器以及如何负责任地使用它们。
- IE 的有条件注释。
- 星号 HTML 过滤器。
- 注释反斜线过滤器和 Holly 招数。
- 反斜线过滤器和修改后的简化框模型招数 (MSBMH)。
- !important 和 下划线过滤器。
- 子过滤器和属性过滤器。
8.1 招数和过滤器简介
8.1.1 关于招数和过滤器的一个警告
使用依赖于解析 bug 的过滤器是一种有点儿冒险的方法。这是因为依赖于 bug 而不是特性。与前面的方法相似,如果解析 bug 被修复了,而你试图修复的 bug 还没有得到解决,那么可能会遇到问题。但是,更严重的是,解析 bug 在浏览器的新版本中可能有新的表现形式。例如,假设 Firefox 的一个新版本有某个解析 bug 。如果使用这个 bug 作为过滤器向 IE 提供不同的宽度值,从而解决专用框模型的问题,那么 Firefox 有可能突然继承这个宽度,这可能会破坏许多站点的设计。
作为一般规则,使用依赖于不支持的 CSS 的过滤器,而不是依赖于某种浏览器 bug 的过滤器,这可能比较安全。
8.1.2 明智地使用招数
与印刷的页面不同,设计在 Web 上的显示方式不但取决于设计者,同样也取决于用户和他们的设置。如果你的设计在 IE5.0 偏了3像素,只要这对站点的其余部分没有严重影响,页面仍然大致良好,那么可能不必修复这个 bug 。如果使用招数来修复一种老式浏览器中不严重的显示 bug,那么不但要做许多额外的工作,而且可能会给未来的浏览器造成问题。请记住,罪魁祸首是 CSS 的浏览器实现,而不是你的站点。
在 CSS 中,有许多方法可以实现同样的效果,所以如果某些东西造成了问题,那么可以尝试另一种方法。许多 CSS 错误是由过分复杂的代码和标记造成的。如果使代码保持简单明了,那么可以避免使用大多数招数。
为了帮助你选择正确的过滤器,几个站点提供了表格来描述哪些过滤器在哪些浏览器中是有效的。这些支持表中最有名、最新的可以在 Centricle(http://centricle.com/ref/css/filters/)和Dithered(www.dithered.com/css_filters)上找到。
8.2 过滤单独的样式表
将招数放在浏览器特定的 CSS 文件中,然后使用过滤器将它们发送给对应的浏览器,这会大大简化招数的管理。当前有两种主要的实现方法。一种方法是使用解析 bug 利用@import 规则将特定的 CSS 文件发送到适当的浏览器。另一种方法是使用 IE 有条件注释。
8.2.1 IE的有条件注释
有条件注释是一种专有的 (因此是非标准的)、对常规 (X)HTML 注释的 Microsoft 扩展。顾名思义,有条件注释使你能够根据条件 (比如浏览器版本) 显示代码块。尽管是非标准的,但是有条件注释对于其他所有浏览器作为常规注释出现,因此本质上是无害的。有条件注释在 Windows 上的 IE5 首次出现,并且得到了 Windows 浏览器的所有后续版本的支持。
要想将一个特定的样式表交给 IE5 和更高的所有版本,那么可以在 (X)HTML 文档的开头放置以下代码:
<!-- [if IE]
<style type="text/css">
@import ("ie.css");
</style>
-->
Windows 上的 IE5 和更高版本会接收样式表 ie.css ,而其他所有浏览器只会看到一些被注释掉的文本。可以使用有条件注释指定一种特定的浏览器,比如 IE 5.0;
<!-- [if IE 5]
<style type="text/css">
@import ("ie50.css");
</style>
-->
还可以指定一组浏览器,比如 IE5.5 和更高版本:
<!-- [if gte IE 5.5000]
<style type="text/css">
@import ("ie55up.css");
</style>
-->
或 IE5 和 IE 5.5
<!-- [if lt IE 6]
<style type="text/css">
@import ("ie.css");
</style>
-->
这种技术极其有效,而且非常容易记住。主要的缺点是这些注释需要放在 HTML 中,而不是放在 CSS 中。如果在某一阶段你希望停止支持某种浏览器,就需要从每个页面中删除注释。
8.3 过滤单独的规则和声明
如果你的 CSS 文件比较小,而且只需要应用少数几个招数,那么可以将相关的过滤器添加到主样式表中。但是要记住,所有这些规则和声明特有的过滤器会给代码添加额外的负担和复杂性。
8.3.1 子选择器招数
最安全的过滤器依赖于未实现的 CSS,而不是浏览器 bug 。因为这些过滤器使用有效的 CSS 选择器来应用有效的声明,所以严格地说,它们根本不是过滤器。它们仅仅是某些浏览器所不能理解的有效 CSS 规则。
这些过滤器中的第一个称为子选择器招数。Windows 上的 IE6 和更低版本不支持子选择器,所以可以使用它对这些浏览器隐藏规则。为了让这种过滤器起作用,必须确保在子选择器前后没有空格。
在这个示例中,使用子选择器招数对 IE 5-6 /Win 隐藏透明的背景 PNG 图像:
html>body {
background-image: url(bg.png);
}
IE7 预期会支持子选择器,还可能会支持 PNG 透明度。通过以这种方式使用子选择器,就允许 IE 的新版本看到透明背景,而不需要修改代码,因而提供了向前兼容性。
8.3.2 属性选择器招数
另一种过滤规则的有趣方法是使用属性选择器。许多现代浏览器 (比如 Safari 和 Firefox) 支持属性选择器,但是 IE6 和更低版本不支持它。因此,可以使用属性选择器在比较高级的浏览器中对类和 ID 应用样式。在这个示例中,使用属性选择器在符合标准的浏览器中将背景 PNG 应用于内容 div 。
div[id="content"] {
background-image: url(bg.png);
}
同样,IE7计划支持属性选择器和 PNG alpha 透明度,这意味着当 IE7 发布时这个方法会自然而然地在 IE7 中起作用。
8.3.3 星号 HTML 招数
最著名且最有用的 CSS 过滤器之一是星号 HTML 招数。这个过滤器非常容易记住,它可以指定 IE6 和更低版本。正如你知道的,HTML 元素被认为是网页上的第一个元素 (即根元素)。但是,IE 的所有当前版本有一个匿名的根元素,它包围着 HTML 元素。可以使用通用选择器指定包围在另一个元素中的 HTML 元素。因为这种情况只在 IE6 和更低版本中出现,所以可以将特定的规则应用于这些浏览器。
* html {
font-size: small;
}
在任何常规的 CSS 规则的开头添加一个通用选择器和一个 html 类型选择器,这样就会对除 IE 之外的所有浏览器隐藏这个规则。使用这个规则最常见的方法是,设置一个希望应用于除 IE 之外的所有浏览器的规则,然后使用星号 HTML 招数在 IE 中覆盖这个规则。例如,IE 将 1 像素的点线错误地显示为难看的虚线。为了避免这些难看的虚线,可以将锚上的鼠标停留边框样式设置为点线,但是在 IE 中覆盖这个规则,让它们显示为实线:
这个 bug 不可能出现在其他浏览器中,而且在 IE7 中可能会被修复。因此,星号 HTML 招数提供了一种相当可靠的指定 IE6 和更低版本的方法。
a:hover {
border: 1px dotted black;
}
* html a:hover {
border-style: solid;
}
8.3.4 IE/Mac 注释反斜线招数
另一个有用的过滤器是注释反斜线招数。Mac 上的 IE5错误地允许在注释内部进行转义,这个过滤器的工作方法是在结束注释字符串前面添加一个反斜线。其他所有浏览器都会忽略这个转义,并且应用后面的规则。但是,IE5/Mac 会认为注释仍然没有结束,因此会把下一个结束注释字符串前面的所有字符都忽略。
/* Hiding from IE5/Mac \*/
#nav a {
width: 5em;
}
/* End Hack */
这个 bug 也是前面的 IE5/Mac 带通过滤器的工作基础。
如果结合使用星号 HTML 招数和注释反斜线过滤器,就成了 Holly 招数 (这个名称来源于它的发明人 Holly Bergevin)。通过结合使用这两个规则,就可以对 Windows 上的 IE6和更低版本应用规则:
/* Hiding from IE5/Mac \*/
* html {
height: 1px;
}
/* End Hack */
这对于修复 Windows 特有的所有 IE bug 非常有用,它可能是目前最常用的过滤器之一。
8.3.8 !important 和下划线招数
有时候,可能希望在同一个规则中对 Windows 上的 IE6 和更低版本应用一个声明,对其他所有浏览器应用另一个声明。为此,可以使用注释属性招数,也可以使用 !important 或下划线招数。
!important 招数之所以能够起作用是因为 Windows 上的 IE6 和更低版本在处理单一规则中的多个属性方面有问题:
#nav {
position: fixed !important;
position: static;
}
IE4-6/Win 会忽略第一个声明并且应用第二个。其他所有浏览器会应用第一个声明,因为它使用了 !important 关键字,这提高了此规则在层叠中的优先级。
下划线招数与 !important 招数相似。在属性前面放一个下划线,符合标准的浏览器就不再认识这个属性并且忽略这个声明。但是 Windows 上的 IE6 和更低版本会忽略下划线,因此应用这个规则。所以,在这个示例中,所有现代浏览器会把 position 设置为 fixed,跳过未知的第二个规则。IE 4-6/Win 会忽略下划线并且覆盖第一个规则,将 position 设置为 static 。
#nav {
position: fixed;
_position: static;
}
补充:
1.类内部 Hack: 比如 IE6 能识别下划线 "_" 和 星号 "*" ,IE7 能识别 星号 "*" ,但不能识别下划线 "_",而 IE8,firefox 两个都不能认识。
2.选择器 Hack: 比如 IE6 能识别 * html .class{} ,IE7 能识别 *+html .class{} 或者 *:first-child+html .class{} 。IE8 两个都不认识。
3."\9" 例如: "border: 1px \9;" 这里的 "\9" 可以区别所有 IE 和 Firefox.
4. "\0" IE8,IE9 识别,IE6、IE7 不能。
5. "\9\0" IE9 识别,IE 8 不能。
书写顺序,一般是将识别能力强的浏览器的 CSS 写在后面。