各浏览器对于获取文档水平及垂直方向滚动条位置(scrollLeft、scrollTop)时的参考元素存在差异
来源:互联网 发布:烟台软件开发公司 编辑:程序博客网 时间:2024/06/07 12:06
问题描述
针对获取页面的垂直滚动条的位置,IE Firefox Opera 标准模式下使用 document.documentElement.scrollLeft 获取页面的水平滚动条位置,而混杂模式下则是使用 document.body.scrollLeft。Chrome Safari 在两种文档模式下均使用 document.body.scrollLeft 获取页面的水平滚动条位置。
同理,针对获取页面的水平滚动条的位置的情况与上面类似。
造成的影响
在混杂模式下,由于所有浏览器均使用 document.body.scrollTop 获取页面的垂直滚动条的位置,所以不会出现兼容性问题。
而在标准模式下,由于 Chrome 与 Safari 仍然使用 document.body.scrollTop,而对于 document.documentElement.scrollTop 返回为 0。这时如果仅仅使用 document.documentElement.scrollTop 获取页面垂直滚动条顶端位置,则在 Chrome 和 Safari 中就会因为永久返回 0 导致页面运行异常(如,绝对定位的元素不能随页面的滚动条而滚动或位置有误)。
对于获取页面的水平滚动条的位置,情况与上面描述类似。
受影响的浏览器
问题分析
Element.scrollTop 及 Element.scrollLeft 不是 W3C 规范的标准属性,最初被 IE 的 DHTML Object Model 引入,但已被目前各主流浏览器所支持。更多参见 MSDN:scrollTop Property 与scrollLeft Property。
- Element.scrollTop 属性获取或者设置一个元素的内容已经滚动到其上边界的像素数。只有在元素具备垂直滚动条的时候此属性才有效。
- Element.scrollLeft 属性获取或者设置一个元素的内容已经滚动到其左边界的像素数。只有在元素具备水平滚动条的时候此属性才有效。
而无论是 MSDN 还是 Mozilla Developer Center,均没有明确提及对于页面(即视口元素)的滚动条,其垂直与水平的位置需要通过哪一个 DOM 对象获取。
分析以下代码:
<html><head><script> var d, str; window.onload = window.onscroll = function () { d = document.getElementById("d"); str = "<strong>" + ((document.compatMode.toLowerCase().indexOf("back") >= 0) ? "Quirks" : "Standards") + "</strong><br />" + "document.documentElement.scrollTop:" + document.documentElement.scrollTop + "<br />" + "document.documentElement.scrollLeft:" + document.documentElement.scrollLeft + "<br />" + "document.body.scrollTop:" + document.body.scrollTop + "<br />" + "document.body.scrollLeft:" + document.body.scrollLeft; d.innerHTML = str; }</script></head><body style="font:12px Arial; _background-attachment:fixed; _background-image:url(about:blank);"><div style="width:10000px; height:10000px;"></div><div id="d" style="position:fixed; top:0; left:0; _position:absolute; _top:expression(offsetParent.scrollTop); _left:expression(offsetParent.scrollLeft); background:#ddd;"></div></body></html>
测试代码中,当在页面中改变垂直滚动条与水平滚动条的位置,会动态地在灰色背景的 DIV 元素中显示出当前页面的文档模式以及 document.documentElement.scrollTop document.documentElement.scrollLeftdocument.body.scrollTop document.body.scrollLeft 这四个属性的返回值。
不同的浏览器运行的结果列表如下:
通过上表可知:
- 在 IE6 IE7 IE8 Firefox Opera 中,标准模式下分别使用 document.documentElement.scrollTop 及document.documentElement.scrollLeft 获取页面的垂直与水平滚动条的位置,混杂模式下使用document.body.scrollTop 及 document.body.scrollLeft 获取页面的垂直与水平滚动条的位置。
- 在 Chrome Safari 中,标准模式与混杂模式下均使用 document.body.scrollTop 及document.body.scrollLeft 获取页面的垂直与水平滚动条的位置。
引申资料:
我们通过 WebKit 内核与 Gecko 内核的源代码中也可以看出 Chrome Safari 与 Firefox 对页面的 scrollTop scrollTop 获取方式的不同:
WebKit 内核:/WebCore/html/HTMLBodyElement.cpp
int HTMLBodyElement::scrollTop() const{ // Update the document's layout. Document* doc = document(); doc->updateLayoutIgnorePendingStylesheets(); FrameView* view = doc->view(); return view ? adjustForZoom(view->scrollY(), view) : 0;}int HTMLBodyElement::scrollLeft() const{ // Update the document's layout. Document* doc = document(); doc->updateLayoutIgnorePendingStylesheets(); FrameView* view = doc->view(); return view ? adjustForZoom(view->scrollX(), view) : 0;}
Gecko 内核:/content/base/src/nsGenericElement.cpp
nsNSElementTearoff::GetScrollInfo(nsIScrollableView **aScrollableView, nsIFrame **aFrame){ ... if ((quirksMode && mContent->NodeInfo()->Equals(nsGkAtoms::body)) || (!quirksMode && mContent->NodeInfo()->Equals(nsGkAtoms::html))) { // In quirks mode, the scroll info for the body element should map to the // scroll info for the nearest scrollable frame above the body element // (i.e. the root scrollable frame). This is what IE6 does in quirks // mode. In strict mode the root scrollable frame corresponds to the // html element in IE6, so we map the scroll info for the html element to // the root scrollable frame. do { frame = frame->GetParent(); if (!frame) { break; } scrollFrame = do_QueryFrame(frame); } ...}
Firefox 的 Gecko 内核源代码中通过对文档模式的判断决定通过哪个对象获取和设置 scrollTop scrollLeft 属性。从注释中可以看到,Firefox 这么做是为了兼容 IE6 的标准模式与混杂模式对这两者的处理。
而 WebKit 内核则没有针对文档模式进行判断,对页面滚动条信息通过 [Object HTMLBodyElement] 对象获取与设置。
解决方案
使用 "||" 逻辑语句将这两种获取方式相连,以保证兼容性。如:
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
- 各浏览器对于获取文档水平及垂直方向滚动条位置(scrollLeft、scrollTop)时的参考元素存在差异
- 获取浏览器垂直滚动条的位置
- 页面滚动时的位置:为了兼容浏览器,封装自己的scrollTop和scrollLeft(内含“怪异模式”)
- js获取浏览器滚动条垂直滚动距离scrollTop的兼容方法
- scrollTop, scrollLeft 滚动条距离
- document.documentElement.scrollTop(获取滚动条位置)
- document.documentElement.scrollTop(获取滚动条位置) .
- 文档滚动对 scrollTop scrollLeft的兼容性封装
- 获取主流浏览器滚动条的位置
- JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
- JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
- JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
- JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
- JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
- 自动滚动的RecyclerView(水平和垂直方向)
- 垂直水平滚动条
- JS获取各种高度宽度、浏览器窗口滚动条的位置、元素的几何尺寸
- JS获取各种高度宽度、浏览器窗口滚动条的位置、元素的几何尺寸
- 开拓思维题目1——四人过桥
- .c和.h文件的区别
- OracleConnection (.NET)
- 匈牙利命名法
- SQL Server 的最大容量规范
- 各浏览器对于获取文档水平及垂直方向滚动条位置(scrollLeft、scrollTop)时的参考元素存在差异
- oracle clob字段 to_char() 缓冲区太小
- Java中的引用概念
- java 位操作运算符
- CocoaPods详解之----进阶篇
- 交互设计资源
- Android WiFi系统
- Android 程序的命名规则
- Codeforces Round #279 (Div. 2)B. Queue