191

How can I get and set the current web page scroll position?

I have a long form which needs to be refreshed based on user actions/input. When this happens, the page resets to the very top, which is annoying to the users, because they have to scroll back down to the point they were at.

If I could capture the current scroll position (in a hidden input) before the page reloads, I could then set it back after it reloads.

Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
xyz
  • 2,059
  • 2
  • 14
  • 8
  • Isn't an AJAX-driven form not a better way to prevent those effects (and of course provide a fallback in case XHR is unavailable)? Page reloads will have the page to jump to the top and back again, a quirk that can be annoying. – Marcel Korpel Nov 04 '10 at 13:13

8 Answers8

188

The currently accepted answer is incorrect - document.documentElement.scrollTop always returns 0 on Chrome. This is because WebKit uses body for keeping track of scrolling, whereas Firefox and IE use html.

To get the current position, you want:

document.documentElement.scrollTop || document.body.scrollTop

You can set the current position to 1000px down the page like so:

document.documentElement.scrollTop = document.body.scrollTop = 1000;

Or, using jQuery (animate it while you're at it!):

$("html, body").animate({ scrollTop: "1000px" });
tobek
  • 4,349
  • 3
  • 32
  • 41
  • 9
    gyo's answer, suggesting `window.pageYOffset` is cleaner if you're using `window.scrollBy()` or `window.scrollTo()` methods. – igorsantos07 Apr 24 '17 at 04:50
185

You're looking for the document.documentElement.scrollTop property.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • thanks, I found this: http://articles.sitepoint.com/article/javascript-from-scratch/6 and modified the `getScrollingPosition()` to store the values in hidden variables. Then in the html of the refreshed page I use ` – xyz Nov 04 '10 at 14:32
  • 50
    I'm finding, on Chrome on Ubuntu at least, that `document.documentElement.scrollTop` is always returning 0. `document.body.scrollTop`, however, seems to work. One Firefox on Ubuntu, on the other hand, the reverse is true - you get 0 with `body` and the correct amount with `documentElement`. Any idea what gives? – tobek Jan 04 '14 at 04:25
  • 21
    This answer is not accurate as the `scrollTop` property doesn't work on all browsers. Check `window.pageXOffset` and `window.pageYOffset` for better results. – gyo Nov 26 '15 at 10:57
65

Update 2021: browsers inconsistencies with scrollTop seem to have disappeared.

There are some inconsistencies in how browsers expose the current window scrolling coordinates. Google Chrome on Mac and iOS seems to always return 0 when using document.documentElement.scrollTop or jQuery's $(window).scrollTop().

However, it works consistently with:

// horizontal scrolling amount
window.pageXOffset

// vertical scrolling amount
window.pageYOffset
gyo
  • 1,663
  • 1
  • 19
  • 28
  • I've noticed it too, is it a bug on Mac and iOS? – Alexander Kim Mar 18 '19 at 12:50
  • @AlexanderKim I think it might be related to how certain CSS rules (like overflow) are interpreted, and it has been reported to work if checking scrollTop on both the body and html elements. However, to avoid testing and debugging, I always rely on the safe and consistent pageXOffset/pageYOffset. – gyo Mar 19 '19 at 14:28
5

I went with the HTML5 local storage solution... All my links call a function which sets this before changing window.location:

localStorage.topper = document.body.scrollTop;

and each page has this in the body's onLoad:

  if(localStorage.topper > 0){ 
    window.scrollTo(0,localStorage.topper);
  }
AXE Labs
  • 4,051
  • 4
  • 29
  • 29
  • 3
    It would be more elegant to use setItem() and getItem() of localStorage and instead back up the scroll position at each link click, store it once when leaving the page: window.addEventListener("beforeunload", function() { localStorage.setItem("scrolly", document.documentElement.scrollTop || document.body.scrollTop); }); – StanE May 15 '15 at 23:26
0

this will give you the px value of scroll from top

document.documentElement.scrollTop
0

Nowadays it seems like the get is working with: window.scrollX and window.scrollY. This could be an alternative way to solve it.

JW Geertsma
  • 857
  • 3
  • 13
  • 19
0
 var stop = true;
  addEventListener('drag', (event) => {
    if (event.clientY < 150) {
      stop = false;
      scroll(-1)
    }
    if (event.clientY > ($(window).height() - 150)) {
      stop = false;
      scroll(1)
    }
    if (document.body.getBoundingClientRect().y === 0){
      stop = true;
    }
    if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
      stop = true;
    }
  });
  addEventListener('dragend', (event) => {
    stop = true;
  });

  var scroll = function (step) {
    var scrollY = $(window).scrollTop();
    $(window).scrollTop(scrollY + step);
    if (!stop) {
      setTimeout(function () { scroll(step) }, 20);
    }
  }
denfedweb
  • 9
  • 1
-1

Now you can also use window.scrollTo({ top: 0, behavior: 'smooth' }); instead of using that jQuery solution above for the animation. Here is the documentation: https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo

vondo
  • 1
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31494331) – Hirbod Apr 12 '22 at 01:01