起因:
今天碰到一个奇怪的问题,ff 以及其他标准浏览器 top :0 可以达到预期效果,而 ie6 这个怪胎非得要 top :1px ,由于只有这一个属性,懒得搞懂 ie6 为什么会这样, 又不想用条件注释这种把一个css文件分成两个,就习惯的用了邪恶的 css hack (Universal* Selector ):
.c {
top:0;
*top:1px;
}
很是不爽,验证都通不过了,不符合完美主义。
原理:
突然想起看得 ext-core 中 EventManager.js 的一段代码,实现了传说中的css标记浏览器方法 :
extjs 会在 html 的 body 元素上 加入 class : ext-gecko ext-gecko3 或 ext-ie6 等类 标志这是哪个浏览器,html 标签上加入 ext-strict 等表示是否处于标准模式 ,(ext-border-box 还没搞清楚干嘛的 ?)
代码:
// 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.isSafari ? "ext-safari" : Ext.isChrome ? "ext-chrome" : ""]; if(Ext.isMac){ cls.push("ext-mac"); } if(Ext.isLinux){ cls.push("ext-linux"); } if(Ext.isStrict || Ext.isBorderBox){ // add to the parent to allow for selectors like ".ext-strict .ext-ie" var p = bd.parentNode; if(p){ p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box'; } } bd.className += cls.join(' '); return true; } if(!initExtCss()){ Ext.onReady(initExtCss); } })();
实践:
这样我们就可以利用css的层叠特性来修改原来的代码:
.c {
top:0;
}
.ext-ie6 .c {
top:1px;
}
则这样 ie6 特殊样式就覆盖了 一般的样式,得到了自己想要的,并且可以通过验证了。
缺点以及适用场景:
不过毕竟 extjs 的识别浏览器的样式,要等到运行后才能添加(Ext.onReady),那么等到页面渲染完毕,extjs 才加入 浏览器特定样式,如果特定浏览器样式影响到已经渲染完毕的元素, 会造成页面闪动。所以我认为这种方法,最好的适应场景是后期效果处理,比如用户点击一个按钮,弹出一个复杂控件,则可以在这个控件中使用这种方法了