CSS Hacks

注:下面的内容没有全部进行实验,因此可能有些有误,以后在开发中遇到再进行修正。

0. 基本概念

因为各个浏览器厂商与版本的差异,尤其是万恶的 IE 存在各种的不标准,因此,在进行页面开发时不免要为 IE 单独写一些 CSS 。本文是针对各大浏览器(主要是 IE)单独写CSS样式的几种方法作总结,主要总结了几种 CSS Hacks,在这里把 类内部Hack选择器前缀Hack条件注释引入CSS文件(按浏览器版本引入具体的CSS文件)、条件注释切换html 标签 都纳入CSS Hacks。

什么是CSS hack ?

由于不同厂商的流览器或某浏览器的不同版本(如IE6-IE11,Firefox/Safari/Opera/Chrome等),对CSS的支持、解析不一样,导致在不同浏览器的环境中呈现出不一致的页面展现效果。这时,我们为了获得统一的页面效果,就需要针对不同的浏览器或不同版本写特定的CSS样式,我们把这个针对不同的浏览器/不同版本写相应的CSS code的过程,叫做CSS hack!

CSS hack的原理

由于不同的浏览器和浏览器各版本对CSS的支持及解析结果不一样,以及CSS优先级对浏览器展现效果的影响,我们可以据此针对不同的浏览器情景来应用不同的CSS。

CSS hack书写顺序

CSS hack书写顺序,一般是将适用范围广、被识别能力强的CSS定义在前面。

CSS hack利弊

一般情况下,我们尽量避免使用CSS hack,但是有些情况为了顾及用户体验实现向下兼容,不得已才使用hack。比如由于IE8及以下版本不支持CSS3,而我们的项目页面使用了大量CSS3新属性在 IE9/Firefox/Chrome 下正常渲染,这种情况下如果不使用css3pie或htc或条件注释等方法时,可能就得让IE8-的专属hack出马了。

关于htc,在《CSS Mastery,Advanced Web Standards Solutions》 P76 中,在介绍PNG的透明度时描述了一种 IE PNG fix 技术:需要使用一种不太为人所知的 Microsoft 专有的 CSS 扩展 —— 行为(behavior)。下载合适的 .htc 文件并在 IE6 专用的样式表中使用它,就可以在任何元素上启用 PNG 透明度。

img, div {
	behavior: url(iepngfix.htc)
}

使用hack虽然对页面表现的一致性有好处,但过多的滥用会造成html文档混乱不堪,增加管理和维护的负担。因此建议少用、慎用hack,未来一定会促使浏览器厂商的标准越来越趋于统一,顺利过渡到标准浏览器的主流时代。抛弃那些陈旧的IE hack,必将减轻我们编码的复杂度,少做无用功。

1. 类内部Hack

举个例子:

.test{ 
	color: #000000; /* FF,OP支持 */
	[color: #000000; color:#00FF00; /* SF,CH支持 */ ???
	
	color: #0000FF\9; /* 所有IE浏览器(ie6+)支持;但是IE8不能识别"*"和"_"的css hack;所以可以这样写hack*/
	*color: #FFFF00; /* IE7支持 */
	_color: #FF0000; /* IE6支持 */
}

在标准模式中,测试:

  • "-" 减号,仅在 IE6 中支持
  • "*" IE7、IE6 都能识别
  • "\9" IE6/IE7/IE8/IE9/IE10都生效
  • "\0" IE8/IE9/IE10都生效,是IE8/9/10的hack
  • "\9\0" 只对IE9/IE10生效,是IE9/10的hack

IE浏览器各版本 CSS hack 对照表

IE浏览器各版本 CSS hack

2. 选择器前缀Hack

选择器前缀法是针对一些页面表现不一致或者需要特殊对待的浏览器,在CSS选择器前加上一些只有某些特定浏览器才能识别的前缀进行hack。

目前最常见的是

*html *前缀只对IE6生效 
*+html *+前缀只对IE7生效 
@media screen\9{...}只对IE6/7生效 
@media \0screen {body { background: red; } }只对IE8有效 
@media \0screen\,screen\9{body { background: blue; } }只对IE6/7/8有效 
@media screen\0 {body { background: green; } } 只对IE8/9/10有效 
@media screen and (min-width:0\0) {body { background: gray; } } 只对IE9/10有效 
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {body { background: orange; } } 只对IE10有效

等等结合CSS3的一些选择器,如html:first-child,body:nth-of-type(1),衍生出更多的hack方式.

Demo:

@media screen and (min-width:0){    
    .hacktest {background-color:black\0;}  /*opera*/  
}    
@media screen and (min-width:0) {    
    .hacktest { background-color:purple\9; }/*  for IE9/IE10  PS:国外有些习惯常写作\0,根本没考虑Opera也认识\0的实际 */  
}   
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {    
   .hacktest { background-color:green; } /* for IE10+ 此写法可以适配到高对比度和默认模式,故可覆盖所有ie10的模式 */  
}   
@media screen and (-webkit-min-device-pixel-ratio:0){ .hacktest {background-color:gray;} }  /*for Chrome/Safari*/  
  
/* #963棕色 :root is for IE9/IE10, 优先级高于@media, 慎用!如果二者合用,必要时在@media样式加入 !important 才能区分IE9和IE10 */  
/*  
:root .hacktest { background-color:#963\9; }   
*/  

更多可以参考:
![结合CSS3的一些选择器衍生出更多的hack方式]
(http://images2015.cnblogs.com/blog/760374/201705/760374-20170508190642504-908768810.jpg)

3. 条件注释 引入CSS文件

同样是上面的例子,如果使用条件注释 CSS ,可以如下编写:

HTML:

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

ie6.css

.demo {
	margin-left: 20px; 
}

这里说明一下:条件注释是一种 IE 专有的、对常规(X)HTML 注释的 Miscrosoft 扩展。从 W3C 标准来说,它也是不标准的产物,但它是微软官方推出的针对 IE 进行开发的方式,并且条件注释对于其他所有浏览器作为常规注释出现,因此对其他浏览器无害。
条件注释 CSS 的好处是在独立的 CSS 文件中编写,能准确控制在特定的 IE 中加载,不会造成资源浪费,并且便于维护。缺点就是会产生多余的 HTTP 请求,尤其是当你需要兼容的 IE 版本很多的时候,你就需要产生多个 HTTP 请求,这对于本来通道数目就少的低版本 IE 来说无疑会影响页面加载速度。
显然,以上的方法都不是很好的方法,因此,接下来介绍一种相对来说更好的解决方案。

4. 条件注释切换 html 标签

这种方式是IE浏览器专有的Hack方式,微软官方推荐使用的hack方式。举例如下

<!--[if IE]> 
这段文字只在IE浏览器显示 
<![endif]--> 

只在IE6下生效 
<!--[if IE 6]> 
这段文字只在IE6浏览器显示 
<![endif]--> 

只在IE6以上版本生效 
<!--[if gte IE 6]> 
这段文字只在IE6以上(包括)版本IE浏览器显示 
<![endif]--> 

只在IE8上不生效 
<!--[if ! IE 8]> 
这段文字在非IE8浏览器显示 
<![endif]--> 

非IE浏览器生效 
<!--[if !IE]> 
这段文字只在非IE浏览器显示 
<![endif]--> 

这种方案也是利用条件注释,但并不是对 CSS 使用条件注释,而是对 html 标签使用条件注释,引入不同的 class ,从而区分不同的 IE 以及其他浏览器。例如:

<!DOCTYPE html>
<!--[if IE 6 ]> <html class="ie6 lte_ie6 lte_ie7 lte_ie8" lang="zh-CN"> <![endif]-->
<!--[if lte IE 6 ]> <html class="lte_ie6 lte_ie7 lte_ie8" lang="zh-CN"> <![endif]-->
<!--[if lte IE 7 ]> <html class="lte_ie7 lte_ie8" lang="zh-CN"> <![endif]-->
<!--[if lte IE 8 ]> <html class="lte_ie8" lang="zh-CN"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html lang="zh-CN"><!--<![endif]-->

然后把针对特定 IE 的 CSS 加上相应的 class 并写在普通 CSS 文件里即可。例如上面的例子则可以在 CSS 文件里编写:

.ie6 .demo {
	margin-left: 20px; 
}

这种方法吸收了条件注释表达式的好处同时又不会产生多余的 HTTP 请求,只是由于这些针对特定 IE 的 CSS 与普通的 CSS 放在一起,即不是相应的 IE 也会被加载,因此如果 CSS 数目比较多的话就会像使用 hacks 那样,造成浪费,开发者需要根据具体情况选择方法。

参考

史上最全的CSS hack方式一览

最后补上一张引自国外某大牛总结的CSS hack表,这时一张6年前的旧知识汇总表了,放在这里仅供需要时候方便参考。
css hack 表

posted @ 2017-05-08 19:04  少东主  阅读(551)  评论(0编辑  收藏  举报