【分享】如何正确的获取scrollTop/scrollLeft的值
前些日子,在做一个类似信息提示窗口的时候,其中有个需求是这个样子的:
提示的窗口要一直位于浏览器的右下角,随页面滚动而滚动。
看起来很简单,当时想到了一种较为简单的方案,那就是使用 “position:fixed;”,利用固定定位实现,很简单,但是,存在兼容性问题,IE6(QS)/IE7(Q)/IE8(Q)下是不支持的。
那个东西还必须兼容IE6,于是我就想到了使用 JS来控制一个绝对定位的元素。通过改变它的位置来使它始终在右下角。
……
后来,用到了一个属性:scrollTop,这个值可以设置或获取位于页面最顶端和窗口中可见内容最顶端之间的距离。
如下图所示:
关于这个值的获取,我一开始是使用的 document.documentElement.scrollTop,后来,发现使用此值在标准模式下还行,但到了兼容性模式下,就必须使用 document.body.scrollTop来获取了。再后来,,发现document.documentElement.scrollTop在 Webkit浏览器Chrome和Safari下取到的值是0。
我决定好好的研究一下这个属性。
scrollTop的兼容性问题
Element.scrollTop 不是 W3C 规范的标准属性,最初被 IE 的 DHTML Object Model 引入,但已被目前各主流浏览器所支持。更多参见 MSDN:scrollTop Property。
Element.scrollTop 属性获取或者设置一个元素的内容已经滚动到其上边界的像素数。只有在元素具备垂直滚动条的时候此属性才有效。
而无论是 MSDN 还是 Mozilla Developer Center,均没有明确提及对于页面(即视口元素)的滚动条,其垂直与水平的位置需要通过哪一个 DOM 对象获取。
分析以下代码:
<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.body.scrollTop:" + document.body.scrollTop; d.innerHTML = str; }</script><body style="font:12px Arial; _background-attachment:fixed; _background-image:url(about:blank);"><div style="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>
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
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;}
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); } ...}