`
hax
  • 浏览: 962455 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

给IE打补丁技巧之CSS Expression

阅读更多
CSS Expression是自IE5开始提供的特性,虽然因安全性、性能问题臭名昭著,到IE8也终于寿终正寝。回过头看,与XMLHttpRequest一样,CSS Expression的理念确实也有先驱之功,从CSS Expression也可看出由jQuery发扬光大的用CSS selector绑定行为的编程方式的雏形。不过雏形只能是雏形。由于设计上的缺陷,CSS Expression不堪大用,通常只局限为patch一些CSS特性,例如min-width/max-width。

不过CSS Expression在patch IE方面其实还可以发挥更大的功用。Dean Edwards首创了一次性执行experssion的模式,巧妙的利用了IE的内建Selector机制,同时又避免了experssion被反复计算的性能问题。这种模式被许多patch所使用。例如Peter Nederlof的hover/active/focus伪类补丁

但是这个模式仍然有不足。Dean使用的是behavior属性。而单个CSS属性只能被用一次,即在一个元素上,最后根据cascade规则只会有一个behavior声明会胜出,因此你无法为一个元素同时启用多个特性(即调用多个行为)。

Peter Nederlof因为要绑定三个行为(分别对应于三个伪类),因此征用了3个不常用的css property(text-kashida, text-kashida-space, text-justify)。

显然,可以征用的css属性是很有限的(比方说你不能把background这样常用的属性给搞坏了,所以西方人也就是会欺负一下日本人专用的CSS属性)。如果能使用任意自定义的css属性的话,就好了。实际上IE对于不认识的property也是可以通过currentStyle返回其cascade之后的值的,而且expression对于自定义property也是有效的。

但是custom property存在一些问题:

1. 无法用runtimeStyle来override自定义属性
2. 即使删除包含expression的stylesheet,expression仍然有效
3. 在expression调用的方法里也不能调用removeExpression来强行删除表达式(会扔异常)

下面我讲一下我对这个问题的研究和解决方法。

根据我的研究,expression的机制与普通CSS属性不同,是设置在每个元素的style上的。

span {
  behavior: expression(test1(this));
  pie-test: expression(test2(this));
}


通常我们可以从currentStyle.propName来得到属性值,但是这样只是得到计算后的结果,且currentStyle上并无getExpresssion方法。但是调用span.style.getExpression('behavior')或('pie-test')会得到'test1(this)'和'test2(this)'

因此可以认为,对于这个rule,相当于对每个span都调用了一次 .style.setExpression('behavior', 'test1(this)') 以及 .style.setExpression('pie-test', 'test2(this)')

且通过对应的 .style.removeExpression 可以清除expression。

但是方法调用有一个限制,就是如果当前在expression所调用的函数(这里就是test2()函数)中,是不能调用 .style.set/removeExpression 方法的,会扔出异常。

设置runtimeStyle.behavior时,也会清除expression,相当于调用了style.removeExpression('behavior'),但是没有上面描述的限制。然而对于自定义属性无效。甚至任何时候runtimeStyle.setExpression('pie-test', null),也不会覆盖style上已经设定的expression。

以上。

显然一个解决方案是在expression之外调用 .style.removeExpression 。

示例代码:
function test2(e) {
  setTimeout(function () {
    e.style.removeExpression('pie-test')
  }, 1)
  ...
}


这是有效的。问题是定时器只能保证最终自定义属性上的expression会被移除,但是不能确保expression只被执行一次(实测下来会执行多少次是不确定的,一次到数次都有可能)。

当然,我们可以给每个元素加上标志位来判断是否已经执行过,不过这还是挺麻烦的。


另一个解决方案是先把元素存起来,然后统一删除expression。

示例代码:
var spans = []
function test(e) {
  spans.push(e)
  ...
}

<head>
...
<script defer>
for (var i = 0; i < spans.length; i++)
  spans[i].style.removeExpression('pie-test')
spans = []
</script>


经过实测defer的script能确保正好执行一次。不过有趣的是如果打印spans.length会发现是在不断增加的,也就是并非所有元素上的test2执行完成后才执行defer的脚本,而是恰好一次test2,一次循环。这个也太巧合了,我对这个行为吃不太准。另外这个方式不能应对后续动态加入的匹配元素,丧失了使用css expression的最大好处之一。


最终的方案是利用CSS的规则。

实际上不是所有expression都会被反复执行。IE其实有基本的优化,比如对于expression(0)就只会计算一次,不会反复求值,因为很容易判断该值是不会变化的。

虽然如前所述不能在test2里直接调用 .style.setExpression ,但是可以通过改变match条件来override expression,如示例代码:
<style>
span {
	pie-test: expression(test2(this));
}
span.pie-test {
	pie-test: expression(true);
}
</style>
<script>
function test2(e) {
  e.className += ' pie-test'
  ...
}
</script>


经过测试该方式可以完美达到只执行一次的目标!

该方法还有个好处,如果要再次执行test2,只需要从元素的class中删除pie-test即可。

后续的blog中我会展示一下使用这个模式来给IE打一些重要的特性补丁。

0
0
分享到:
评论
2 楼 hautbbs 2011-09-27  
还有木有更详细的资料啊?
1 楼 cloudgamer 2010-10-25  
技巧很好很有意思

相关推荐

    IE6, IE7, IE8 CSS 兼容速查表

    10. **CSS Expression**:IE6和7支持CSS表达式,但这种动态计算属性的性能较差,应尽量避免使用。 以上只是部分兼容性问题的概述,完整的速查表将包含更多细节,如每个CSS属性在不同IE版本中的表现、解决方法以及...

    让IE6、IE7、IE8支持CSS3的圆角、阴影样式

    3. **CSS Hack**:对于某些简单的圆角效果,可以使用特定的CSS hack针对IE6-8编写样式,例如使用`expression`或`filter`属性。但这种方法并不推荐,因为它会导致代码复杂性增加,且性能较差。 4. **渐进增强**:...

    ie-css3(让ie6 ie7 ue8支持css3).rar

    7. **注意事项**:尽管这类解决方案可以增强旧版IE的CSS3支持,但仍然可能存在兼容性和性能问题,且不建议过度依赖此类技术,因为它们可能影响网站的维护性和稳定性。随着IE浏览器逐渐被淘汰,关注现代浏览器和符合...

    兼容IE的最小最大高度CSS写法

    尤其是对于那些仍需支持Internet Explorer(IE)的老项目,由于IE对现代CSS特性的支持不足,开发者需要采取一些特殊的技术手段来实现兼容性。本文将详细介绍一种兼容IE的最小最大高度CSS写法,并通过实际代码示例...

    IE8升IE10补丁.rar

    【标题】"IE8升IE10补丁.rar"是一个包含Windows 7系统从Internet Explorer 8(IE8)升级到Internet Explorer 10(IE10)所需更新的压缩包文件。这个补丁主要是为了解决在内网环境下无法正常升级IE浏览器的问题。 ...

    让ie也支持css3

    【标题】"让ie也支持css3"指的就是通过一种技术手段使老旧的IE浏览器能够识别并应用CSS3的一些新特性。这通常涉及到一种名为`.htc`(HTML Component)的文件格式,它是微软特有的HTC行为技术,可以将JavaScript或者...

    IE6、IE7、IE8对css和js支持方面差异的研究

    在探讨IE6、IE7、IE8对CSS和JavaScript支持的差异时,我们可以发现一系列显著的兼容性问题和解析规则的变化。以下是对这些差异的详细分析: 1. **JavaScript性能和垃圾收集**: - 在IE6中,JScript引擎在处理大量...

    IE不支持的集中css

    【标题】:“IE不支持的集中css” 【描述】中提到的是一些在IE浏览器,特别是IE6中不受支持的CSS属性。了解这些属性对于优化IE兼容性具有重要意义,可以帮助开发者更有针对性地编写CSS和使用Hack。 【标签】:“IE...

    iecss3.htc支持输入框圆角

    这时,我们就需要借助于一些特殊的技术来实现对IE浏览器的兼容,比如“iecss3.htc”文件。 “iecss3.htc”是一种行为(Behavior)文件,它是微软Internet Explorer特有的扩展,通过VML(Vector Markup Language)来...

    DIV+CSS相对IE6、IE7和IE8的兼容问题

    以上内容详细介绍了在面对IE6、IE7和IE8等老旧浏览器时,如何运用CSS技巧来克服布局上的兼容性问题。这些策略不仅有助于提升网页的跨浏览器兼容性,还能保证在不同设备和环境下的用户体验一致性。

    最全的CSS浏览器兼容问题整理(IE6、IE7)

    【CSS浏览器兼容问题详解】 在Web开发中,CSS(层叠样式表)的浏览器兼容性问题...随着技术的发展,现代浏览器对CSS的支持已经大大增强,但仍需关注老版本浏览器的兼容性,尤其是企业级应用中可能仍存在的IE6/7用户。

    针对firefox ie6 ie7 ie8的css样式hack

    在进行Web开发的过程中,我们经常会遇到浏览器兼容性问题,尤其是早期的Internet Explorer(IE)版本如IE6、IE7和IE8与现代浏览器如Firefox之间的差异。为了确保网站能够在不同浏览器下正常显示,开发者需要使用特定...

    CSS样式兼容IE6、IE7、IE8、FF火狐浏览器的方法

    在探讨CSS样式兼容IE6、IE7、IE8与火狐浏览器的方法时,我们需深入理解不同浏览器对CSS的支持差异,以及如何通过特定的技术手段确保网页在这些浏览器中的一致性和美观性。以下是对这一主题的详细解析: ### 1. 了解...

    IE6.0、IE7.0 与FireFox CSS兼容的解决方法

    在网页设计中,CSS(层叠样式表)的兼容性问题常常困扰着开发者,尤其是在处理IE6.0、IE7.0与Firefox等不同浏览器之间的差异。以下是一些解决这些浏览器间CSS兼容问题的方法: 1. **DOCTYPE声明**:DOCTYPE声明会...

    CSS中expression使用简介

    CSS中的`expression`是一个特性,...因此,虽然`expression`在早期Web开发中提供了一种创新的解决方案,但在现代Web开发中,为了兼容性、性能和代码质量,应避免使用`expression`,转而使用标准的CSS和JavaScript技术。

    第十四节 IE中利用CSS触发XSS-01

    从IE5开始得到支持,但由于标准、性能、安全性等问题,微软从IE8 beta2标准模式开始,取消对css expression的支持。 注释绕过关键字过滤 在CSS中,可以使用注释来绕过关键字过滤。例如,使用 `//` 绕过对关键字 `...

    ie6下可以用的css3

    标题中的“ie6下可以用的css3”指的是在Internet Explorer 6(简称IE6)这款老版本的浏览器中,可以通过特定的技术实现CSS3的一些效果。IE6是2001年发布的,当时CSS3规范尚未完全成熟,因此默认不支持CSS3的许多新...

    尽量不要使用CSS Expression的原因

    CSS Expression在其它浏览器中不起作用,因此在跨浏览器的编码中单独针对IE设置时会比较有用。从IE5开始支持CSS Expression。我们看下面的代码:background-color: [removed] (new Date()()).getHours()%2 ? "#F00" ...

    css解决IE6,IE7,firefox兼容性问题.

    本文旨在详细介绍如何通过 CSS hack 技术以及调整 CSS 属性来解决 IE6、IE7 及 Firefox 之间的兼容性问题。 #### 二、CSS Hack 技术 CSS Hack 是一种特殊的 CSS 编写技巧,用于向特定版本的浏览器提供不同的样式...

    兼容IE8插件(兼容h5+css3新特性)

    这是一个对IE8及以下做前端兼容的文件工具...--对于ie6到ie8做兼容,兼容h5,css3等新特性--&gt; &lt;!--[if (gte IE 6)&(lte IE 8)]&gt; [removed][removed] [removed][removed] [removed][removed] &lt;![endif]--&gt;

Global site tag (gtag.js) - Google Analytics