【分享】深入挖掘 offsetParant 元素的判定
时间:2010-08-06
来源:互联网
对于元素A的offsetParent,W3C标准的 CSSOM 规范,对此作了规定。我们现在就跟据标准挖掘一下,各浏览器到底是不是一致,是不是遵守标准。
如何元素 A 的 offsetParant 元素 B
A是根元素或 BODY 则 offsetParent 元素为null
HTML code
<html id="_html"> <script> function op(id) { var off = document.getElementById(id); return id + " offsetParent : " + (!!off.offsetParent ? off.offsetParent : "null"); } window.onload = function() { document.getElementById("info").innerHTML = op("_body") + "</br>" + op("_html"); } </script> <body id="_body"> <div id="info"></div> </body> </html>可见,html和body的offsetParent 都不存在。这时,不存在兼容性问题。
A的 position特性计算后的值是 fixed 则 offsetParent元素为null
HTML code
<html id="_html"> <script> function op(id) { var off = document.getElementById(id); return id + " offsetParent : " + (!!off.offsetParent ? off.offsetParent.id : "null"); } window.onload = function() { document.getElementById("info").innerHTML = op("_fixed"); } </script> <body id="_body"> <div id="_fixed" style="position:fixed;">fixed</div> <div id="info"></div> </body> </html>此时,存在兼容性问题。
Opera/Chrome/Safari中输出的是:_fixed offsetParent : null
Firefox/IE中会输出:_fixed offsetParent : _body
可见,在Firefox和IE中,固定定位的元素的offsetParent是 BODY 元素,明显是不符合W3C标准的。注意,在IE中 BODY 是默认拥有布局的,BODY是默认触发hasLayout的。
position 特性计算后的值是非 ‘static’ 的祖先元素B
HTML code
<html id="_html"> <script> function op(id) { var off = document.getElementById(id); return id + " offsetParent : " + (!!off.offsetParent ? off.offsetParent.id : "null"); } window.onload = function() { document.getElementById("info").innerHTML = op("_normaldiv"); } </script> <body id="_body"> <div id="_positioned" style="position:relative;"> <div id="second"> <div id="_normaldiv"></div> </div> </div> <div id="info"></div> </body> </html>所有浏览器中的输出都是:_normaldiv offsetParent : _positioned
此时无兼容性问题。
修改一下代码,<div id="second">外面再套一个 DIV,并且此 DIV 在IE中触发了hasLayout(设置了 ‘width:100px;’):
HTML code
<html id="_html"> <script> function op(id) { var off = document.getElementById(id); return id + " offsetParent : " + (!!off.offsetParent ? off.offsetParent.id : "null"); } window.onload = function() { document.getElementById("info").innerHTML = op("_normaldiv"); } </script> <body id="_body"> <div id="_positioned" style="position:relative;"> <div id="first" style="width:100px;"> <div id="second"> <div id="_normaldiv"></div> </div> </div> </div> <div id="info"></div> </body> </html>这时,情况发生变化了,IE6/IE7/IE8(Q) 中的输出变成了:_normaldiv offsetParent : first
其他浏览器中还是:_normaldiv offsetParent : _positioned
看来,在IE中,元素的offsetParent 是离它最近的触发hasLayout的元素。
HTML body类型的祖先元素B
HTML code
<html id="_html"> <script> function op(id) { var off = document.getElementById(id); return id + " offsetParent : " + (!!off.offsetParent ? off.offsetParent.id : "null"); } window.onload = function() { document.getElementById("info").innerHTML = op("_normaldiv"); } </script> <body id="_body"> <div id="_positioned"> <div id="first" style="width:100px;"> <div id="second"> <div id="_normaldiv"></div> </div> </div> </div> <div id="info"></div> </body> </html>IE6/IE7/IE8(Q) 中输出:_normaldiv offsetParent : first
其他浏览器中:_normaldiv offsetParent : _body
将 first 的style属性去掉,在IE6/IE7/IE8(Q) 中输出:_normaldiv offsetParent : _body
A的 position 特性计算后的值是 static 并且其祖先元素B是 TD/TH/TABLE元素
HTML code
<html id="_html"> <script> function op(id) { var off = document.getElementById(id); return id + " offsetParent : " + (!!off.offsetParent ? off.offsetParent.id : "null"); } window.onload = function() { document.getElementById("info").innerHTML = op("_th") + "<br/>" + op("_td") + "<br/>" + op("_positoinedinth") + "<br/>" + op("_positoinedintd") + "<br/>" + op("_inth") + "<br/>" + op("_intd") + "<br/>"; } </script> <body id="_body"> <table id="_table"> <tr id="_tr"> <th id="_th"> <div id="_inth">in th</div> <div id="_positoinedinth" style="position:relative;">positoined in th</div> </th> <td id="_td"> <div id="_intd">in tr</div> <div id="_positoinedintd" style="position:relative;">positoined in th</div> </td> </tr> </table> <div id="info"></div> </body> </html>从上面测试代码中,可以看出:
● IE6(Q)/IE7(Q)/IE8/Firefox/Chrome/Safari/Opera中,非static元素的 offsetParent 都是 BODY
● IE6(S)/IE7(S)中很奇怪,非static元素的 offsetParent 竟然是 HTML。
● 所有浏览器中,TD 和 TH 的 offsetParent 是TABLE,这跟标准是符合的。
● static定位元素的 offsetParent 不是TD/TH/TABLE。应该根据上面已经说明的规则向上查找。注意,<table>, <tr>, <th>, <td> 都会自动触发hasLayout。
IE中的offsetParent究竟是什么
综合以上测试结果,可以得到一个结论,在IE中的offsetParent元素的取值算法,跟其他浏览器不同:
● 对于static定位的元素,其offsetParent是离它最近的触发hasLayout的元素。
● 对于非static定位的元素,则是离它最近的非static定位的元素。如果不存在,在IE6(S)/IE7(S)下取 HTML 元素,其他情况下去 BODY元素。
不知上述总结是否严密,还请大伙一起检查、讨论,欢迎拍砖……
扩展阅读:
hasLayout: http://msdn.microsoft.com/en-us/library/ms533776(VS.85).aspx
大伙儿还可以讨论一下,怎么样才能有效的避免这个问题???Thx。
现实意义何在
知道这些差异,可以让你取出的坐标更加准确,让你的定位更加准确,所以,绕开IE的hasLayout很有必要,但是很难。
还是多多注意吧!
资料:
W3C: http://www.w3.org/TR/cssom-view/#dom-htmlelement-offsetparent
更多兼容性问题:
【分享】浏览器兼容性问题目录
作者: WebAdvocate 发布时间: 2010-08-06
作者: ixuxiansi 发布时间: 2010-08-06
作者: ixuxiansi 发布时间: 2010-08-06
作者: bq0wyl 发布时间: 2010-08-06
作者: zzx461618420 发布时间: 2010-08-06
作者: zzx461618420 发布时间: 2010-08-06
作者: hzw20100709 发布时间: 2010-08-06
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28