看看下面这段代码,是否倍感亲切但又觉得很陌生呢:
.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 的写法了。