让IE6支持min-width
最新更新,在IE7中_width: expression中的表达示还会被计算,所以要考虑好脚本的兼容性。
最近和同事在搞一个自适应布局的页面改版,样式里用到了一些min-width,这个CSS属性在IE6里不被支持。要解决这个问题,网上大多数都是用IE的expression去解决的(不了解expression的同学看下http://msdn.microsoft.com/en-us/library/ms537634%28v=vs.85%29.aspx)。expression有个特点就是,当元素reflow/repaint的时候,它都会重复运算一次。虽说可以解决min-width的兼容问题,但是性能损耗太大了,而且页面上用的min-width越多,这个性能损耗会随之变大。下面是用expression实现min-width的代码
1
2
3
4
5
6
7
8 |
<style type= "text/css" > #target { min-width : 800px ; _width : expression(this.parentNode.clientWidth > 800 ? 'auto' : '800px' ); height : 100px ; background : red ; } </style> |
为了解决用expression的性能损耗问题,我又考虑到用JavaScript去实现。思路很简单,就是把在expression里面的逻辑搬到window.onresize这个事件处理函数中,以达到重新布局的目的。但是问题又来了,想重新布局页面元素,就要拿到这个元素的句柄,如果是带有id的元素事情到不是很复杂,如果是在类选择器里用到了min-width,事情就不是那么容易了。虽然有jQuery之类的类库帮我们选择元素,但这也是一笔不小的性能开销,而且代码变得难于维护,要是日后对min-width有所更改的话,还要同时去改JS。
总结一下,碰到的问题有以下两点:
- 在CSS中用expression实现min-width会造成大量不必要的计算
- 在JS中用window.onresize重新设定元素宽度会涉及到:1),如何取元素句柄的问题;2),JS代码不够简洁难于维护,修改样式的同时还要改JS;
结合上面的分析,最好的情况就是在CSS定义里面为window绑定onresize事件处理函数,然后在函数里面对当前DOM元素实现重新布局。听起来不可思议的事情,在IE6中变得很容易,因为expression的本质就是一段js代码,在里面可以调用页面中声明的其它JS函数,可以写成_zoom: expression(someFunc(min-width-value));的形式。此处的someFunc是通过JS声明的函数,在里面实现对window.onresize的绑定,每当窗口改变的时候,将元素的宽度重新设置成min-width-value。在CSS定义中可以这么写 #target {min-width: 800px; _zoom: expression(someFunc(’800px’)); } 样式的定义都放在一处,维护起来也容易,这样就解决了上述第二点的问题。
到目前为止,当元素需要reflow/repaint的时候,expression还是不断的去调用someFunc,这也是第一点问题。其实解决的办法很容易,就是在someFunc的最后一行调用 this.style.zoom=1;这样在以后的重绘中zoom的值恒为1,就不会重新计算expression了。至此所以问题都已解决。下面就是真实的代码了。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < html xmlns = "http://www.w3.org/1999/xhtml" xml:lang = "en" > < head > < meta http-equiv = "Content-Type" content = "text/html;charset=GBK" /> < title >测试IE6的min-width</ title > < style type = "text/css" > #target { min-width: 800px; _width: expression(minWidth(this, 800)); height: 100px; background: red; } </ style > </ head > < body > < div id = "target" ></ div > < script type = "text/javascript" > (function() { var isIE6=!-[1,]&&!window.XMLHttpRequest, elements = []; function reflow(elem, value) { elem.style.width = elem.parentNode.clientWidth > value ? 'auto': value + 'px'; } window.minWidth = function(elem, value) { if(isIE6) { reflow(elem, value); elements.push({ 'elem': elem, 'value': value }); } else { elem.style.width = 'auto'; } }; if(isIE6) { var timer; window.attachEvent('onresize', function() { var handler = arguments.callee; clearTimeout(timer); timer = setTimeout(function() { // 注销掉事件,防止reflow里触发onresize而导致的死循环 window.detachEvent('onresize', handler); for(var i = 0, len = elements.length; i < len ; i++) { var element = elements [i]; reflow(element.elem, element.value); } window.attachEvent('onresize', handler); }, 50); }); } }()); </script> </ body > </ html > |
有一点值得注意,就是如何在expression中拿到元素的句柄。
建议继续学习:
- 解决IE6从Nginx服务器下载图片不Cache的Bug (阅读:7082)
- IE6下position:absolute相邻元素margin-top失效的bug (阅读:3058)
- IE6中a标签location.href失效解决方法 (阅读:2405)
- IE6下appendChild的一个小问题。 (阅读:2221)
- IE6浮动引起的一些BUG (阅读:2210)
- 这到底是谁之错? (阅读:1468)
- IE6下经典的请求abort问题 (阅读:1393)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:小寒 来源: 记事本
- 标签: IE6 min-width
- 发布时间:2012-08-22 23:53:20
- [66] Oracle MTS模式下 进程地址与会话信
- [65] 如何拿下简短的域名
- [65] Go Reflect 性能
- [59] 【社会化设计】自我(self)部分――欢迎区
- [59] IOS安全–浅谈关于IOS加固的几种方法
- [59] 图书馆的世界纪录
- [59] android 开发入门
- [53] 视觉调整-设计师 vs. 逻辑
- [47] 界面设计速成
- [47] 读书笔记-壹百度:百度十年千倍的29条法则