众所周产于公元2002年、且当前为我国主流的IE6浏览器是不支持CSS2的静止定位属性fixed,蛋疼的前端工程师们为此发明了各种形式的解决方案:
一、常规js解决之道
这个方案最为古老,比IE6还老,且应用十分广泛:比如很多跟着滚动条走的对联广告就是使用此方案。缺点就是拖动滚动条元素抖动很厉害,虽然通过平滑处理可以改善下,效果仍然不理想。不过要说的是此方案虽然视觉效果差了那么一点,稳定性与可控性没得二话说的。
二、动用HTML结构与布局模拟法
此方案曾经被163博客应用,163把所有的内容放在一个高度100%且滚动条设置为自动的容器中,然后再下面设置一个绝对定位的层,这样这个绝对定位的层就可以达到静止状态。原理:你拖动的滚动条并不是拖动的整个页面,而是那个模拟整页的容器,所以容器外的地方都是“静止”的。详细:
http://bbs.blueidea.com/thread-2930592-1-1.html
这里视觉效果达到完美,问题有三:
- 1、需要改变HTML结构(此项不解释)
- 2、破坏了用户体验:我曾经也试过此方法,但是我刷新页面的时候滚动条不会停留在原处,这点我不能容忍。
- 3、破坏js一些事件,如cloudgamer提到会破坏window的scroll事件,这里至少可以让N多封装好的js组件失效。
三、前无古人的“清空法”之火星方法解决
原理实在离奇,我解释不了,并且应用的局限性太大了。例子见:
http://bbs.blueidea.com/thread-2938030-1-1.html
四、老技术新用的expression加fixed背景方案
此方案能够视觉上完美的实现静止定位。例子:
这两种方案本来已经很完美了,我artDialog早期版本也是这么实现的,可是后来使用过程中发现了一个更加不能容忍的BUG,我在回复cloudgamer写了BUG触发DEMO:
http://bbs.blueidea.com/viewthread.php?tid=3001496&page=1#pid5047726
这个问题的本质就是用expression模拟fixed外包裹元素实际是设置了absolute,并且遮盖了页面,IE6可能导致其下页面一些元素无法响应事件,如div、td、span等,只有a、button、input等元素可以响应,那些无法响应事件的元素如果包含了文字BUG又会消失。这个美丽的效果下藏了这么一个大坑,让我们情何以堪……
是的,我原来很崇尚这个方案,因为视觉效果完美并且相对简单。但是它的BUG让我万念俱灰,甚至都想放弃对IE6 fixed支持,时不时的以“渐进增强”来说服自己,本身fixed更多的意义是一个视觉效果,重要性不能与absolute的相提并论……好吧,我要说的是有了解决上述BUG的方法,所以“渐进增强”的想法又被我抛到脑后去了(吃不到葡萄就说葡萄酸,吃到了葡萄就甜了..),下面的DEOM代码是我四天前写好的,直到今天才在自己Blog上分享,希望彻底埋了第上述第四方案的坑了:
五、使用js 设置 expression 与 removeExpression 法
04 | <meta http-equiv= "Content-Type" content= "text/html; charset=utf-8" /> |
05 | <title>ie6 Fixed</title> |
09 | <p><button id= "fixedBtn" >设置静止定位</button><button id= "fixedBtn2" >改变位置</button></P> |
10 | <P><button id= "absoluteBtn" >设置绝对定位</button><button id= "absoluteBtn2" >改变位置</button></P> |
11 | <div id= "fixed" style= "width: 60px; height:60px; background:#C0C0C0; border:solid 1px #000;" ></div> |
12 | <div style= "height:1400px;" title= "请拖动滚动条" ></div> |
13 | <script type= "text/javascript" > |
14 | var position = function (){ |
15 | var isIE6 = !-[1,] && !window.XMLHttpRequest, |
16 | html = document.getElementsByTagName( 'html' )[0], |
17 | dd = document.documentElement, |
21 | getScroll = function (win){ |
23 | left: Math.max(dd.scrollLeft, db.scrollLeft), |
24 | top: Math.max(dd.scrollTop, db.scrollTop) |
31 | if (isIE6 && document.body.currentStyle.backgroundAttachment !== 'fixed' ) { |
32 | html.style.backgroundImage = 'url(about:blank)' ; |
33 | html.style.backgroundAttachment = 'fixed' ; |
37 | fixed: isIE6 ? function (elem){ |
38 | var style = elem.style, |
40 | dom = '(document.documentElement || document.body)' , |
41 | left = parseInt(style.left) - doc.left, |
42 | top = parseInt(style.top) - doc.top; |
44 | style.setExpression( 'left' , 'eval(' + dom + '.scrollLeft + ' + left + ') + "px"' ); |
45 | style.setExpression( 'top' , 'eval(' + dom + '.scrollTop + ' + top + ') + "px"' ); |
47 | elem.style.position = 'fixed' ; |
50 | absolute: isIE6 ? function (elem){ |
51 | var style = elem.style; |
52 | style.position = 'absolute' ; |
53 | style.removeExpression( 'left' ); |
54 | style.removeExpression( 'top' ); |
56 | elem.style.position = 'absolute' ; |
62 | var elem = document.getElementById( 'fixed' ); |
63 | document.getElementById( 'fixedBtn' ).onclick = function (){ |
64 | elem.style.left = '100px' ; |
65 | elem.style.top = '100px' ; |
68 | document.getElementById( 'fixedBtn2' ).onclick = function (){ |
69 | elem.style.left = '400px' ; |
70 | elem.style.top = '100px' ; |
73 | document.getElementById( 'absoluteBtn' ).onclick = function (){ |
74 | elem.style.left = '100px' ; |
75 | elem.style.top = '100px' ; |
76 | position.absolute(elem); |
78 | document.getElementById( 'absoluteBtn2' ).onclick = function (){ |
79 | elem.style.left = '400px' ; |
80 | elem.style.top = '100px' ; |
81 | position.absolute(elem); |
新窗口打开演示文档
在实现了ie6 fixed的前提下,实际应用中可能还需要对这个fixed元素调整位置,如鼠标拖拽元素。上面的DEMO同样是使用expression实现,不同的是expression直接应用到了要操作的对象上,这样就不会发生上述BUG了,直接设置在元素上后再想手动改变元素位置(如拖动)是相当困难的,必须有一个可以重置expression的方法,而前些天在msdn上看到的removeExpression方法,问题迎刃而解!你也可以看artDialog3在IE6 fixed的表现。
如果光说到标准的fixed定位除了left与top之外还有right与bottom属性,显然目前此方案支持它们会比较麻烦,还好就是这两个属性在javascript组件中很少用到,不是吗?当然我们如能在能力与精力的范围内满足需求是最好不过的了,如果有更好的方案欢迎提出!
planeart.cn原创文章,原文地址:http://www.planeart.cn/?p=877