Goodbye to CSS Hack
看看下面这段代码,是否倍感亲切但又觉得很陌生呢:
.test {
background-color: black; /* firefox, opera, ie8 */
[;background-color: green;] /* safari, chrome */
*background-color: blue; /* ie7 */
_background-color: red; /* ie6 */
}
html*~/**/body .test {
border: 5px solid red; /* ie8 */
}
随着浏览器的更新换代,CSS Hack 变得越来越诡异和不可靠了-.-
相对来说,IE 的条件注释是值得信赖的:
<!--[if lt IE 7 ]><body class="ie6"><![endif]-->
<!--[if IE 7 ]><body class="ie7"><![endif]-->
<!--[if IE 8 ]><body class="ie8"><![endif]-->>
<!--[if !IE]>--><body><!--<![endif]-->
<style type="text/css">
body.ie6 .test { background-color: blue }
body.ie7 .test { background-color: red }
body.ie8 .test { background-color: green }
</style>
注意,上面的代码虽然也是 hack,但大大简化和规范了 css hack 的写法。
最近看 ExtCore 3.0 的代码,发现 Ext 初始化时会自动给 body 添加浏览器信息:
//Initialize doc classes
(function(){
var initExtCss = function(){
// find the body element
var bd = document.body || document.getElementsByTagName('body')[0];
if(!bd){ return false; }
var cls = [' ',
Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
: Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
: Ext.isOpera ? "ext-opera"
: Ext.isWebKit ? "ext-webkit" : ""];
if(Ext.isSafari){
cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
}else if(Ext.isChrome){
cls.push("ext-chrome");
}
if(Ext.isMac){
cls.push("ext-mac");
}
if(Ext.isLinux){
cls.push("ext-linux");
}
if(Ext.isBorderBox){
cls.push('ext-border-box');
}
if(Ext.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
var p = bd.parentNode;
if(p){
p.className += ' ext-strict';
}
}
bd.className += cls.join(' ');
return true;
}
if(!initExtCss()){
Ext.onReady(initExtCss);
}
})();
比如在 IE8 下,会添加以下信息:

将浏览器信息添加到 body 和 html 上后,我们书写 CSS Hack 就会变得很容易了。
通过 JS 添加浏览器信息,需要将 JS 放在头部执行,以确保渲染前就添加好。另外,对于不支持 JS 的用户代理,此方法无效。
还有一个方案是在服务器端处理,比如 browscap 方案。优点的是没有 JS 方案的缺点,缺点是遇上 proxy cache 就不准确了。
个人觉得 JS 方案可行。因为禁用 JS 的浏览器用户,自身已是高手,不用我们担心。对于不支持 JS 的用户代理,比如手机等浏览器,则有对应的 WAP 版本给用户使用。这样,我们可以:
- 在 head 部分加载一个非常小巧精简的 js,该 js 在 body 可用时,能立刻给 body 添加浏览器信息。
- 在 css 里,通过
body.ie6 .test { ... }来书写 css hack
这样,无论浏览器如何更新换代,我们都不必去记忆或发掘那一堆诡异的 css hack 的写法了。

June 23rd, 2009 on 13:08
我顶你,玉伯。我觉得可行~~~!
June 23rd, 2009 on 13:13
我也觉得这个功能靠谱
之前一直喜欢IE的条件注释
June 23rd, 2009 on 13:34
还是像麦鸡一样直接屏蔽IE的好些~
June 23rd, 2009 on 13:36
这个做法不错, 我也一直郁闷着呢, 那么多的hack看得人头晕眼花的!
June 23rd, 2009 on 13:45
我之前有篇文章《body标签class属性的妙用(Google Reader前端简单分析)》观点类似
http://www.99css.com/2009/04/bodyclassgoogle-reader.html
June 23rd, 2009 on 14:03
非css hack方案是很爽,但是总给人不稳定感。
June 23rd, 2009 on 14:07
我觉得这里存在着一个问题:
通过JS判断浏览器来完成CSS HACK,
但是JS往往是在 document.ready()
之后执行的,也就是说页面已经加载完
毕后再重置CSS,会不会造成页面抖动
或者闪动?
这方面我不是太了解,请问:
DOM 树没有加载完的情况下,能取到浏览器类型么?
June 23rd, 2009 on 14:28
太好了,希望能放出文中提到的:“一个非常小巧精简的 js”
June 23rd, 2009 on 16:42
7楼的说的太片面了,当然不都是ready之后才执行的。
June 23rd, 2009 on 18:14
hack是一种态度,哈哈
June 23rd, 2009 on 21:47
现在的浏览器都在朝W3C标准的大一统的方向发展,CSS Hacks迟早要成为历史
June 23rd, 2009 on 21:48
hack总是给人一种缺憾感,在没有太明显差异情况下还是不要“招惹”它,发扬“惹不起,躲得起”的风格
June 24th, 2009 on 8:43
这种办法有个不好地方就是用到hack的地方都要以body.ie6 等开头如:body.ie6 .class1 .class2 .class3{padding-top:2px},选择符太长
June 24th, 2009 on 11:29
个人认为浏览器应该是越更新越贴近标准吧,如果显示都一样了为什么还关心Hack呢?
June 24th, 2009 on 14:18
还是通过js载入单独的css hack file比较好吧……
June 24th, 2009 on 15:31
学习
June 24th, 2009 on 18:21
下个项目用这个方法试试…
June 25th, 2009 on 17:25
按照渐进增强的原则,这个思路不太合适。
June 27th, 2009 on 0:50
好文~~~受益匪浅。
唯独不明白的是,不懂ExtCore 3.0。看不懂那段ExtCore 3.0的代码。
不知用普通的js该如何写?
博主是否能举个例子(包括HTML调用)?谢谢。
June 28th, 2009 on 1:58
原来你是玉伯?
June 30th, 2009 on 17:13
思路不错。通过服务器端添加特定标识貌似比js来的更靠谱。
July 2nd, 2009 on 16:24
ext 一直这么做的,
比如 你以前说的 selector 突出 mask问题 ,ext window 就是这样解决的:
body.ext-ie6.x-body-masked select {
visibility:hidden;
}
body.ext-ie6.x-body-masked .x-window select {
visibility:visible;
}
很早国外有人在sourceforge上就放了个很小的js文件,就是自动给html,body加附带浏览器信息的class
我找找
July 4th, 2009 on 11:22
我比较关心” 一个非常小巧精简的 js” 。。。。
July 10th, 2009 on 14:22
那ext 3.0兼容性应该会更好了.
July 29th, 2009 on 14:38
Amaranth said:
“我比较关心” 一个非常小巧精简的 js” 。。。”
同問。
August 5th, 2009 on 15:21
yahoo!的新首页是在服务器端处理的。
August 5th, 2009 on 16:52
@爱商·爱尚
本人写了一个”小巧精简的”JS,欢迎大家测试。
http://files.cnblogs.com/wanghongyuan/goodbye_to_css_hack.rar
August 6th, 2009 on 13:44
既然都是用js方法来实现的,也许用js判断浏览器类型然后加载补丁css会更方便于管理。
August 6th, 2009 on 17:47
不错,这个方法非常好,比各种Hack清晰多了
August 14th, 2009 on 14:00
命名空间~哈哈,的趣的Hack~
August 31st, 2009 on 16:55
jquery有个browser插件 http://jquery.thewikies.com/browser/#examples ,测试了304+浏览器 http://jquery.thewikies.com/browser/test.html,会在html标签上加上几个浏览器的相关class,比如IE6:,达人们可以研究一下
August 31st, 2009 on 21:01
仿佛似曾相识, 老雕貌似发过类似的观点博文.
November 21st, 2009 on 3:07
非常好~~~学习了
December 1st, 2009 on 15:32
用W3C标准的话 基本就用不到CSS HACK了 很多情况下 要用CSS HACK的时候 你其实 找一找别的办法 同样能解决 CSS HACK真的已经是历史咯
December 7th, 2009 on 11:57
讨论可不可用 太难了
我觉得你需要讨论你会不会去这样用,这只是一种习惯。
我觉得挺好的,自然会去想办法尽量让这种方法可用
leave a reply