目录
当前位置: 首页 > 文档资料 > 揭秘 CSS >

10.2.1 CSS Hack

优质
小牛编辑
120浏览
2023-12-01

开发人员基本都知道,CSS的开发本身并不难,但是,当在不同的浏览器下测试代码时,困难就出现了。浏览器的 bug 和不一致的显示方式,是大多数CSS开发人员面临的主要难题,你的设计在一种浏览器上看起来很好,而在另一种浏览器上可能会支离破碎。

实践证明,CSS的兼容性主要有两种情况:一种是对老版本IE的兼容性,一种是使用CSS3新特性后产生的兼容性。

对老版本IE的兼容性,主要通过CSS Hack和客户端脚本来解决;对使用CSS3新特性后产生的兼容性,主要通过浏览器私有前缀来解决。

CSS Hack

由于不同厂商的浏览器(如IE、Chrome、Firefox、Safari),或同一浏览器的不同版本(如IE6~IE11),对CSS的解析不完全一样,导致同一页面在不同浏览器中的效果可能不一致。

为了得到统一的效果,就需要针对不同浏览器,或同一浏览器的不同版本,编写不同的CSS,把这个过程就被称作CSS Hack。

实践证明,CSS Hack主要用来解决IE的兼容性问题。虽然它是强有力的工具,但应该谨慎使用,它一般作为修复问题的最后一道屏障,在不得已的时候才会使用。因为更重要的是跟踪、隔离和识别问题,而不是修复问题。只有真正了解问题背后的原理,才能找到最好的解决方案。

CSS Hack 有 3 种表现形式:

1)属性前缀或后缀法

即在定义样式规则时,为样式属性添加只有特定浏览器,或某浏览器特定版本才能识别的前缀或后缀。

表 10-1 常见的前缀后缀说明及应用示例
前缀/后缀适用版本应用示例
_IE6p { _color: blue; }
-IE6p { -color: blue; }
+IE7p { +color: blue; }
*IE6/IE7p { *color: blue; }
#IE6/IE7/IE8p { #color: blue; }
!importantIE7/IE8/IE9/IE10/IE11p { color: blue !important; }
\9IE6/IE7/IE8/IE9/IE10/IE11p { color: blue\9; }
\0IE8/IE9/IE10/IE11p { color: blue\0; }
\9\0IE9/IE10/IE11p { color: blue\9\0; }

在使用属性前缀或后缀法时,一般是将适用范围广、被识别能力强的写法写在前面,把特殊写法写在后面。如:

div {  
    background: blue;
    background: green\9; 
    *background: black; 
    _background: orange; 
}  

由于所有浏览器都识别标准写法,而IE6/IE7/IE8/IE9/IE10/IE11可识别\9,IE6/IE7可识别*,IE6仅能识别_。根据CSS的叠加原理,后定义的属性会覆盖先定义的同名属性,就实现了为IE各版本和现代浏览器应用不同样式的目的。

2)选择器前缀法

即在CSS选择器前,添加只有特定浏览器或某浏览器特定版本才能识别的前缀,选择器和前缀之间用空格分隔。

常用的前缀有 *html 和 *+html,*html 是IE6特有的前缀,而 *+html 是IE7特有的前缀。如:

*html p { color: blue; }   /* IE6 */
*+html p { color: blue; }  /* IE7 */

3)条件注释法

条件注释是IE浏览器专有的,也是微软官方推荐的Hack方式。它是使用IE条件注释,针对不同IE版本,编写不同的CSS,来为不同版本的IE应用不同的样式。

一种方法是直接在条件注释中定义样式。如:

<style>
<!--[if IE 6]>
div {
   display: inline; 
}
<![endif]-->
</style>

虽然这种方法可以解决一些现实的问题,但这些注释需要放在HTML文件,而不是CSS文件中,样式定义散落在多个地方,不便于维护,也容易出错。也违背了内容与表现相分离的原则,故不推荐使用。

另一种方法是,编写不同的CSS文件,再使用IE条件注释,通过 <link> 标签,有针对性的加载外部样式表。如:

<!--[if IE 6]>
<link rel="stylesheet" href="css/ie6.css" />
<![endif]-->

这种方法却会增加IE用户的HTTP请求次数,影响访问速度。所以,在使用这种方法前,要仔细斟酌,判断是否真的有必要在自己的网站上使用它。

一个好消息是,从IE10版本开始,不再支持条件注释。这标志着IE从此走向成熟、走向标准,Web设计师再也不必为IE的兼容性问题所困扰了。

愿望是美好的,现实却是残酷的。很多WEB设计师仍然发现,相同的CSS,在IE9/10/11上的渲染效果,和其它现代浏览器还是不一样。

也就是说,我们仍然需要条件注释。那么,在不支持条件注释的IE10/11上,能够实现条件注释的效果呢?

答案是肯定的。并且,有多种方法可以实现条件注释的替代效果。并且,它们有各自的应用场景,可以根据需要选择使用。

方法一:使用IE = EmulateIE9属性,指示浏览器采用IE9渲染模式:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9">

因为IE9是支持条件注释的,在页面的头部加入以上的元数据后,IE10/11就使用IE9的渲染模式,自然就能识别条件注释了。

很显然,这样做的弊端是,浏览器使用的是IE9的渲染模式,而不是最新的IE10/11的渲染模式。

方法二:使用媒体查询语句的 +-ms-high-contrast 属性,为不同浏览器应用不同的样式。

CSS 的媒体查询语句是一种高级的CSS条件语句,它能根据一些属性和属性值的计算结果,来判断CSS是否可以生效。

由于只有IE10/11实现了 -ms-high-contrast 属性,取值为active或none。因此,就可以使用以下媒体查询语句:

@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
    /* IE10+ CSS styles go here */
}

Firefox浏览器、Chrome浏览器不能识别这个属性,这个语句中的CSS就不会生效,便间接实现了条件注释的效果。

方法三:使用Javascript判断浏览器的类型,来为不同浏览器定义不同的样式。

先用Javascript 判断浏览器的类型,如果是IE浏览器,就在页面的 <html> 标签上添加一个 ie 的类名:

<script>
var ms_ie = false;
var ua = window.navigator.userAgent;
var old_ie = ua.indexOf("MSIE");
var new_ie = ua.indexOf("Trident/");

if ((old_ie > -1) || (new_ie > -1)) {
    ms_ie = true;
}

if ( ms_ie ) {
    document.documentElement.className += "ie ";
}
</script>

有了这个标志性 class 后,就可以在CSS中,区分不同的浏览器,并专门针对IE编写不同的CSS代码。如:

.testClass{
    /* 这里写通用的css */
}

.ie .testClass{
    /* 这里写专门针对IE的css */
}

事实上,这个方法还能区分老IE和新IE。因此,也可以区分老IE和新IE,并有针对性的编写不同的CSS代码。

方法四:使用IE10/11私有的条件编译特性,来区分IE6-9 和IE10/11。

<!--[if !IE]>
<script>
if (/*@cc_on!@*/false)  {
    document.documentElement.className += "ie10  ";
}
</script>
<!--<![endif]-->

上述脚本中,先使用条件注释 !IE来排除IE,以确保IE6-9不承认它。然后,再执行@ cc_on功能检测。