240

I'm hoping to find a way to get the current viewable window's position (relative to the total page width/height) so I can use it to force a scroll from one section to another. However, there seems to be a tremendous amount of options when it comes to guessing which object holds the true X/Y for your browser.

Which of these do I need to make sure IE 6+, FF 2+, and Chrome/Safari work?

window.innerWidth
window.innerHeight
window.pageXOffset
window.pageYOffset
document.documentElement.clientWidth
document.documentElement.clientHeight
document.documentElement.scrollLeft
document.documentElement.scrollTop
document.body.clientWidth
document.body.clientHeight
document.body.scrollLeft
document.body.scrollTop

And are there any others? Once I know where the window is I can set an event chain that will slowly call window.scrollBy(x,y); until it reaches my desired point.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Xeoncross
  • 55,620
  • 80
  • 262
  • 364

5 Answers5

309

The method jQuery (v1.10) uses to find this is:

var doc = document.documentElement;
var left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
var top = (window.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0);

That is:

  • It tests for window.pageXOffset first and uses that if it exists.
  • Otherwise, it uses document.documentElement.scrollLeft.
  • It then subtracts document.documentElement.clientLeft if it exists.

The subtraction of document.documentElement.clientLeft / Top only appears to be required to correct for situations where you have applied a border (not padding or margin, but actual border) to the root element, and at that, possibly only in certain browsers.

thomasrutter
  • 114,488
  • 30
  • 148
  • 167
  • Thomas -- you're totally right. My bad. Comments removed. I re-read your comment and realized that your solution wasn't a Jquery solution at all. Apologies. Modded up. – Bangkokian Jan 21 '15 at 12:22
  • It works now. I think they had a very temporary bug in webkit and they fixed it already. I wrote a plugin the completely broke because of that bug and users reported to me of this. Very scary such basic things might break – vsync Feb 16 '15 at 09:40
  • 3
    Is this the code for $(window).scrollTop(); ? It would probably be useful to include the jQuery method as well in this answer. – Phil Aug 18 '15 at 16:55
  • 1
    The code I posted is a paraphrasing of what became `jQuery.fn.offset()`. `scrollTop()` / `scrollLeft()` do basically the same, but don't subtract clientTop / clientLeft. – thomasrutter Aug 28 '15 at 04:52
  • What is the method? – Maxrunner Sep 12 '16 at 15:59
  • As I said above this is from jQuery's `jQuery.fn.offset()` function, though it is paraphrased rather than copied directly. – thomasrutter Sep 13 '16 at 00:29
  • Would it be possible to add the jQuery equivalent math? Just for followers use. Thanks! – rogerdpack Oct 13 '16 at 19:59
  • scrollY has no support in IE and potentially poor support in Edge and Safari – thomasrutter May 17 '18 at 23:58
232

Maybe more simple;

var top  = window.pageYOffset || document.documentElement.scrollTop,
    left = window.pageXOffset || document.documentElement.scrollLeft;

Credits: so.dom.js#L492

Kerem
  • 11,377
  • 5
  • 59
  • 58
  • 2
    Perfectly cross browser safe! Best solution. – Simon Steinberger May 09 '15 at 07:45
  • 1
    That worked better than the answer code, but... the answer code doesn't worked, not a bit... –  Sep 02 '15 at 19:00
  • 2
    I wonder why not just use `document.documentElement.scrollTop` which works everywhere. – vsync Jul 01 '18 at 11:42
  • These days, all of the above are aliases of window.scrollY on all modern browsers, with the exception of MSIE (all versions). As long as MSIE11 is still on the scene window.pageYOffset is probably the best works-anywhere until you can drop MSIE altogether. – thomasrutter Apr 27 '21 at 04:56
38

Using pure javascript you can use Window.scrollX and Window.scrollY

window.addEventListener("scroll", function(event) {
    var top = this.scrollY,
        left =this.scrollX;
}, false);

Notes

The pageXOffset property is an alias for the scrollX property, and The pageYOffset property is an alias for the scrollY property:

window.pageXOffset == window.scrollX; // always true
window.pageYOffset == window.scrollY; // always true

Here is a quick demo

window.addEventListener("scroll", function(event) {
  
    var top = this.scrollY,
        left = this.scrollX;
  
    var horizontalScroll = document.querySelector(".horizontalScroll"),
        verticalScroll = document.querySelector(".verticalScroll");
    
    horizontalScroll.innerHTML = "Scroll X: " + left + "px";
      verticalScroll.innerHTML = "Scroll Y: " + top + "px";
  
}, false);
*{box-sizing: border-box}
:root{height: 200vh;width: 200vw}
.wrapper{
    position: fixed;
    top:20px;
    left:0px;
    width:320px;
    background: black;
    color: green;
    height: 64px;
}
.wrapper div{
    display: inline;
    width: 50%;
    float: left;
    text-align: center;
    line-height: 64px
}
.horizontalScroll{color: orange}
<div class=wrapper>
    <div class=horizontalScroll>Scroll (x,y) to </div>
    <div class=verticalScroll>see me in action</div>
</div>
Gildas.Tambo
  • 22,173
  • 7
  • 50
  • 78
1

Maybe this has not been mentioned due to this article been 11 years old.

But currently I am using window.scrollY (inside an onscroll event listner and a throttle function) and it works just fine most of the time. And when it doesn't I use intersectionObserver API for similar effect which is also a fairly new feature I guess.

if (window.scrollY > desiredAmount) {
   doThis();
}
-1
function FastScrollUp()
{
     window.scroll(0,0)
};

function FastScrollDown()
{
     $i = document.documentElement.scrollHeight ; 
     window.scroll(0,$i)
};
 var step = 20;
 var h,t;
 var y = 0;
function SmoothScrollUp()
{
     h = document.documentElement.scrollHeight;
     y += step;
     window.scrollBy(0, -step)
     if(y >= h )
       {clearTimeout(t); y = 0; return;}
     t = setTimeout(function(){SmoothScrollUp()},20);

};


function SmoothScrollDown()
{
     h = document.documentElement.scrollHeight;
     y += step;
     window.scrollBy(0, step)
     if(y >= h )
       {clearTimeout(t); y = 0; return;}
     t = setTimeout(function(){SmoothScrollDown()},20);

}
ali.b.y
  • 67
  • 2