:before和:after我们经常会用到,特别是在做移动端页面时,利用它制作文字前后的ICON、图片的垂直居中之类的非常方便且代码简洁(当然,功能远比这些要多的多...)。
可是在PC端,由于现在还要考虑到IE6、7的兼容性问题,使用这俩小神器时心情还是会不由地变沉重些,有时还得借助额外的标签来实现,活生生地让其它现代浏览器浪费功能(老早遇到这情况总是会喊一声:SBIE!!),点击查看:before的浏览器支持情况
其实能让IE6、7支持(准确说是模拟):before、:after的方法会有很多种:
(1):额外添加标签(和没说一样~~哈哈);
(2):使用第三方插件,如jquery.pseudo.js;
(3):JS动态添加,如zxx的实现:http://www.zhangxinxu.com/wordpress/2012/11/before-after-use-web/;
(4):其它方法(又和没说一样~~MD)。
有一次在网上乱逛,无意间看到有人在CSS中利用expression()动态创建DOM,我突然有一种捡到50块钱的感觉~~~。抛开性能和规范性的问题不讲,这个expression()确实很适合来弥补IE6、7不支持:before和:after的问题,原理其实都一样,但重要的是:简单、易用。
.test {
/* 在.test中动态创建span标签,并插入到第一个子元素的位置 */
*zoom: expression(this.insertBefore(document.createElement("span"),this.firstChild));
}
在IE6、7中使用上面的样式后,你会神奇的发现,你的浏览器不一会儿就死掉了~~~ 对的,因为expression中的JS语句会不停地执行,Never stop the beat~~~哈哈,直到die,这时就要用一个方法来控制JS语句仅在expression第一次解析时执行,不用flag变量,请出runtimeStyle这个DOM属性,这个属性和currentStyle类似,顾名思义,是运行时的样式,是IE特有的(在Chrome和Firefox中访问它会返回undefined),我们添加一句this.runtimeStyle.zoom="1",将zoom值由原本的expression()设置为一个固定值(这里为1),即而使expression生命仅存在一次,这样便达到了仅在第一次执行expression中的JS代码时添加DOM的目的。
添加控制语句后:
.test {
/* 在.test中动态创建span标签,并插入到第一个子元素的位置 */
*zoom: expression(this.runtimeStyle.zoom="1",this.insertBefore(document.createElement("span"),this.firstChild));
}
这样.test中真的多出了一个span,且在第一个子元素的位置,但是如果要为这个span精确地定义css样式,我们还需要做一些工作,比如:为这个span添加一个class类名,可以这样:
.test {
/* 在.test中动态创建span标签,并插入到第一个子元素的位置 */
*zoom: expression(this.runtimeStyle.zoom="1",this.insertBefore(document.createElement("span"),this.firstChild).className="ie-before");
}
这样子,我们就可以通过.ie-before这个类名来实现样式定义啦:
.test:before,
.test .ie-before {
content: "";
display: inline-block;
backgrund: url("***.jpg");
}
模拟:after的方法一样,区别只是添加DOM的方式,:before是向前添加,:after是向后添加:
.test {
/* 在.test最后一个元素后动态创建span标签 */
*zoom: expression(this.runtimeStyle.zoom="1",this.appendChild(document.createElement("span")).className="ie-after");
}
.test:after,
.test .ie-after{
content: "";
display: inline-block;
backgrund: url("***.jpg");
}
但是有一个问题,:before和:after可以使用content实现与标签元素属性的绑定,比如:
<div class="test" title="你好">吗?</div>
<div class="test" title="我好">吗?</div>
<div class="test" title="大家都好">吗?</div>
.test:before {
content: attr(title);
color: red;
}
上面的结构在IE8+、FF、Chrome中是可以达到你所要的结果的,但在IE6、7下呢?我们可以做一些调整:
.test {
/* 在.test中动态创建span标签,并插入到第一个子元素的位置 */
*zoom: expression(this.runtimeStyle.zoom="1",this.insertBefore(document.createElement("span"),this.firstChild).className="ie-before");
}
.test:before,.
test .ie-before {
content: attr(title);
color: red;
/* IE6\7 */
*zoom: expression(this.runtimeStyle.zoom='1',this.innerText=this.parentNode.title);
}
看看效果如何??呵呵,还不错吧。
其实如果expressioin中的JS语句可以更多更灵活,可以实现更多的需求,但是考虑到如果将expression应用在数量较大的DOM上时,那么还是会有可能崩溃,所以还是要慎重啊。