如何正确的获取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 对象获取。
分析如下代码:  
HTML code
 
   
< 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 >
当浏览器窗口滚动的时候,会在左上角显示出 scrollTop的值。
在Opera,IE,Firefox,Chrome和Safari中测试的汇总表:  

可见,scrollTop能够从document.body和 document.documentElement中获取。
在混杂模式下,全部浏览器均使用 document.body.scrollTop 获取页面的垂直滚动条的位置。因此,在混杂模式下不会出现兼容性问题。
而在标准模式下,Chrome 与 Safari 仍然使用 document.body.scrollTop,同时document.documentElement.scrollTop 的返回为 0。这时若是仅仅使用document.documentElement.scrollTop 获取页面垂直滚动条顶端位置,在 Chrome 和 Safari 中就会由于永久返回 0 致使页面功能异常(如,绝对定位的元素不能随页面的滚动条而滚动或位置有误)。

解决方式

因此,在获取这个值的时候,能够采用如下方法避免兼容性问题:
JScript code
 
   
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
另外,scrollLeft的状况跟scrollTop相似,有兴趣的童鞋能够研究研究。

引伸阅读:

后来请较了一位朋友,把源码给挖出来了。
咱们经过 WebKit 内核与 Gecko 内核的源代码中也能够看出 Chrome、Safari 与 Firefox 对页面的 scrollTop、scrollTop 获取方式的不一样:
WebKit 内核: /WebCore/html/HTMLBodyElement.cpp  
C/C++ code
 
   
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
C/C++ code
 
   
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 的标准模式与混杂模式对 scrollTop、scrollLeft 的处理。

而 WebKit 内核则没有针对文档模式进行判断,对页面滚动条信息经过 [Object HTMLBodyElement] 对象获取与设置。

转载于:https://www.cnblogs.com/sky100/articles/1790505.htmlhtml