原文地址: 小昱博客 - 常见的CSS Hack 转载请注明出处,谢谢!

什么是CSS hack

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

CSS hack的原理

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

CSS hack分类

CSS Hack大致有3种表现形式,CSS属性前缀法、选择器前缀法以及IE条件注释法(即HTML头部引用if IE)Hack,实际项目中CSS Hack大部分是针对IE浏览器不同版本之间的表现差异而引入的。

  • 属性前缀法(即类内部Hack):例如 IE6能识别下划线""和星号" * ",IE7能识别星号" * ",但不能识别下划线"",IE6~IE10都认识"\9",但firefox前述三个都不能认识。
  • 选择器前缀法(即选择器Hack):例如 IE6能识别html .class{},IE7能识别+html .class{}或者*:first-child+html .class{}。
  • IE条件注释法(即HTML条件注释Hack):针对所有IE(注:IE10+已经不再支持条件注释): ,针对IE6及以下版本: 。这类Hack不仅对CSS生效,对写在判断语句里面的所有代码都会生效。

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

CSS hack方式一:条件注释法

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

	只在IE下生效
<!--[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 hack方式二:类内属性前缀法

属性前缀法是在CSS样式属性名前加上一些只有特定浏览器才能识别的hack前缀,以达到预期的页面展现效果。

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

hack 写法 实例 IE6(S) IE6(Q) IE7(S) IE7(Q) IE8(S) IE8(Q) IE9(S) IE9(Q) IE10(S) IE10(Q)
* *color 青色 Y Y Y Y N Y N Y N Y
+ +color 绿色 Y Y Y Y N Y N Y N Y
- -color 黄色 Y Y N N N N N N N N
_ _color 蓝色 Y Y N Y N Y N Y N N
# #color 紫色 Y Y Y Y N Y N Y N Y
\0 color:red\0 红色 N N N N Y N Y N Y N
\9\0 color:red\9\0 粉色 N N N N N N Y N Y N
!important color:blue !important;color:green; 棕色 N N Y N Y N Y N Y Y

说明:在标准模式中

  • “-″减号是IE6专有的hack
  • “\9″ IE6/IE7/IE8/IE9/IE10都生效
  • “\0″ IE8/IE9/IE10都生效,是IE8/9/10的hack
  • “\9\0″ 只对IE9/IE10生效,是IE9/10的hack

demo如下

<script type="text/javascript">
//alert(document.compatMode);
</script>
<style type="text/css">
body:nth-of-type(1) .iehack{
color: #F00;/* 对Windows IE9/Firefox 7+/Opera 10+/所有Chrome/Safari的CSS hack ,选择器也适用几乎全部Mobile/Linux/Mac browser*/
}
.demo1,.demo2,.demo3,.demo4{
width:100px;
height:100px;
}
.hack{
/*demo1 */
/*demo1 注意顺序,否则IE6/7下可能无法正确显示,导致结果显示为白色背景*/
background-color:red; /* All browsers */
background-color:blue !important;/* All browsers but IE6 */
*background-color:black; /* IE6, IE7 */
+background-color:yellow;/* IE6, IE7*/
background-color:gray\9; /* IE6, IE7, IE8, IE9, IE10 */
background-color:purple\0; /* IE8, IE9, IE10 */
background-color:orange\9\0;/*IE9, IE10*/
_background-color:green; /* Only works in IE6 */
*+background-color:pink; /* WARNING: Only works in IE7 ? Is it right? */
} /*可以通过javascript检测IE10,然后给IE10的<html>标签加上class=”ie10″ 这个类 */
.ie10 #hack{
color:red; /* Only works in IE10 */
} /*demo2*/
.iehack{
/*该demo实例是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序
IE6显示为:绿色,
IE7显示为:黑色,
IE8显示为:红色,
IE9显示为:蓝色,
Firefox/Chrome显示为:橘色,
(本例IE10效果同IE9,Opera最新版效果同IE8)
*/
background-color:orange; /* all - for Firefox/Chrome */
background-color:red\0; /* ie 8/9/10/Opera - for ie8/ie10/Opera */
background-color:blue\9\0; /* ie 9/10 - for ie9/10 */
*background-color:black; /* ie 6/7 - for ie7 */
_background-color:green; /* ie 6 - for ie6 */
} /*demo3
实例是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序
IE6显示为:红色,
IE7显示为:蓝色,
IE8显示为:绿色,
IE9显示为:粉色,
Firefox/Chrome显示为:橘色,
(本例IE10效果同IE9,Opera最新版效果也同IE9为粉色) */
.element {
background-color:orange; /* all IE/FF/CH/OP*/
}
.element {
*background-color: blue; /* IE6+7, doesn't work in IE8/9 as IE7 */
}
.element {
_background-color: red; /* IE6 */
}
.element {
background-color: green\0; /* IE8+9+10 */
}
:root .element { background-color:pink\0; } /* IE9+10 */ /*demo4*/
/* 该实例是用于区分标准模式下ie6~ie10和Opera/Firefox/Chrome的hack,本例特别要注意顺序
IE6显示为:橘色,
IE7显示为:粉色,
IE8显示为:黄色,
IE9显示为:紫色,
IE10显示为:绿色,
Firefox显示为:蓝色,
Opera显示为:黑色,
Safari/Chrome显示为:灰色, */
.hacktest{
background-color:blue; /* 都识别,此处针对firefox */
background-color:red\9; /*all ie*/
background-color:yellow\0; /*for IE8/IE9/10 最新版opera也认识*/
+background-color:pink; /*for ie6/7*/
_background-color:orange; /*for ie6*/
} @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; }
*/
</style>

demo1是测试不同IE浏览器下hack 的显示效果

IE6显示为:粉色,

IE7显示为:粉色,

IE8显示为:蓝色,

IE9显示为:蓝色,

Firefox/Chrome/Opera显示为:蓝色,

若去掉其中的!important属性定义,则IE6/7仍然是粉色,IE8是紫色,IE9/10为橙色,Firefox/Chrome变为红色,Opera是紫色。是不是有些奇怪:除了IE6以外,其他所有的表现都符合我们的期待。那为何IE6表现的颜色不是_background-color:green;的绿色而是*+background-color:pink的粉色呢?其实是最后一句所谓的IE7私有hack惹的祸?不是说*+是IE7的专有hack吗?错,你可能太粗心了!我们常说的IE7专有*+hack的格式是*+html selector,而不是上面的直接在属性上加*+前缀。如果是为IE7定制特殊样式,应该这样使用:

*+html #ie7test { /* IE7 only*/
color:green;
}

经过测试,我发现属性前缀*+background-color:pink;只有IE6和IE7认识。而*+html selector只有IE7认识。所以我们在使用时候一定要特别注意。

demo2实例是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序

IE6显示为:绿色,

IE7显示为:黑色,

IE8显示为:红色,

IE9显示为:蓝色,

Firefox/Chrome显示为:橘色,

(本例IE10效果同IE9,Opera最新版效果同IE8)

demo3实例也是用于区分标准模式下ie6~ie9和Firefox/Chrome的hack,注意顺序

IE6显示为:红色,

IE7显示为:蓝色,

IE8显示为:绿色,

IE9显示为:粉色,

Firefox/Chrome显示为:橘色,

(本例IE10效果同IE9,Opera最新版效果也同IE9为粉色)

demo4实例是用于区分标准模式下ie6~ie10和Opera/Firefox/Chrome的hack,本例特别要注意顺序

IE6显示为:橘色,

IE7显示为:粉色,

IE8显示为:黄色,

IE9显示为:紫色,

IE10显示为:绿色,

Firefox显示为:蓝色,

Opera显示为:黑色,

Safari/Chrome显示为:灰色,

CSS 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方式,具体的可以参考下表:

CSS3选择器结合JavaScript的Hack

我们用IE10进行举例:

由于IE10用户代理字符串(UserAgent)为:Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0),所以我们可以使用JavaScript将此属性添加到文档标签中,再运用CSS3基本选择器匹配。

JavaScript代码:

var htmlObj = document.documentElement;
htmlObj.setAttribute('data-useragent',navigator.userAgent);
htmlObj.setAttribute('data-platform', navigator.platform );

CSS3匹配代码:

html[data-useragent*='MSIE 10.0'] #id {
color: #F00;
}

CSS hack利弊

一般情况下,我们尽量避免使用CSS hack,但是有些情况为了顾及用户体验实现向下兼容,不得已才使用hack。比如由于IE8及以下版本不支持CSS3,而我们的项目页面使用了大量CSS3新属性在IE9/Firefox/Chrome下正常渲染,这种情况下如果不使用css3pie或htc或条件注释等方法时,可能就得让IE8-的专属hack出马了。使用hack虽然对页面表现的一致性有好处,但过多的滥用会造成html文档混乱不堪,增加管理和维护的负担。相信只要大家一起努力,少用、慎用hack,未来一定会促使浏览器厂商的标准越来越趋于统一,顺利过渡到标准浏览器的主流时代。抛弃那些陈旧的IE hack,必将减轻我们编码的复杂度,少做无用功。

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

说明:本文测试环境为IE6~IE10,Chrome 29.0.1547.66 m,Firefox 20.0.1 ,Opera 12.02等。

参考资料 : 史上最全的CSS hack方式一览

常见的CSS Hack的更多相关文章

  1. 常见ie css hack

    .all IE{property:value\9;} .gte IE 8{property:value\0;} .lte IE 7{*property:value;} .IE 8/9{property ...

  2. 常见浏览器CSS hack方法总结

    ie6和ie7 #tip {*background:black; /*IE7 背景变黑色*/_background:orange; /*IE6 背景变橘色*/} IE8和IE9 :root .test ...

  3. 常见浏览器兼容问题、盒模型2种模式以及css hack知识讲解

    什么是浏览器兼容问题?所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况.在大多数情况下,我们的需求是,无论用户用什么浏览器来查看我们的网站或者登陆我们 ...

  4. CSS Hack技术介绍及常用的Hack技巧集锦

    一.什么是CSS Hack? 不同的浏览器对CSS的解析结果是不同的,因此会导致相同的CSS输出的页面效果不同,这就需要CSS Hack来解决浏览器局部的兼容性问题.而这个针对不同的浏览器写不同的CS ...

  5. 聊聊css hack

    什么是CSS hack CSS hack由于不同厂商的浏览器,比如Internet Explorer,Safari,Mozilla Firefox,Chrome等,或者是同一厂商的浏览器的不同版本,如 ...

  6. 常用的CSS Hack

    一.什么是CSS Hack? 不同的浏览器对CSS的解析结果是不同的,因此会导致相同的CSS输出的页面效果不同,这就需要CSS Hack来解决浏览器局部的兼容性问题.而这个针对不同的浏览器写不同的CS ...

  7. CSS hack方式一览【转】

    做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道 ...

  8. css样式 --- CSS hack

    前端样式,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道一 ...

  9. 史上最全的CSS hack方式一览

    做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道 ...

随机推荐

  1. ROS 多台计算机联网控制机器人

    0. 时间同步 sudo apt-get install chrony 1. ubuntu自带的有openssh-client 可以通过如下指令 ssh username@host 来连接同一局域网内 ...

  2. 【Python】多线程-线程池使用

    1.学习目标 线程池使用 2.编程思路 2.1 代码原理 线程池是预先创建线程的一种技术.线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中.这些线程都是处于睡眠状态,即均为启动,不消耗 ...

  3. 关于MySQL 8.0的几个重点【转】

    转自 关于MySQL .0的几个重点,都在这里 https://mp.weixin.qq.com/s/QUpk9uuS2JTli1GT6HuORA 一.关于MySQL Server的改进 1.1 re ...

  4. DOS命令大全(转)

    dos命令大全 CMD是command的缩写,是windows环境下的虚拟DOS窗口,提供有DOS命令,功能强大,如果你以前学习过DOS操作,那就小儿科了.是基于Windows的命令行窗口,在开始-- ...

  5. bootgrid修改成可以全勾选和全取消勾选操作

    1. 引言 由于项目需要,需要在不同页面上选择全勾选能全部勾选所有的记录,反勾选也如此.这个需求可以解决了一个样例:如果有150条记录,当前页就10条,你又在每一个页面勾选部分的记录,然后,如果你要全 ...

  6. Python-JS事件与面向对象操作

    目录一.函数高级 循环绑定: 使用循环绑定会出现的问题及解决方案: 二.面向对象 3.构造函数(ES5) 三.JS选择器 1.getElement系列(最严谨) 2.querySelector系列(最 ...

  7. 使用@property - 廖雪峰的官方网站

    使用@property 阅读: 20616 在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9 ...

  8. 《LINQ技术详解C#》-4.LINQ到对象

    public static string[] Presidents { get; } = { "Adams", "Arthur", "Buchanan ...

  9. python全栈开发day36-IO多路复用

    一.复习 1.进程.线程.协程 进程:是计算机中最小的资源分配单位,数据隔离,可以利用多核,数据不安全 线程:是计算机中最小的CPU调度单位,数据共享,GIL,数据不安全 协程:是线程的一部分,是由用 ...

  10. Nordic Collegiate Programming Contest NCPC 2017-Problem D-Distinctive Character

    题目大意:给你n(n<=1e5)个二进制串 (每个串位数不超过20),定义两个串的相似度为对应 位置上相同的个数. 让你构造一个二进制串,使这个串与所给的这些串的相似度的最小值最大. 思路:刚开 ...