262

I need to detect if a user is scrolled to the bottom of a page. If they are at the bottom of the page, when I add new content to the bottom, I will automatically scroll them to the new bottom. If they are not at the bottom, they are reading previous content higher on the page, so I don't want to auto-scroll them since they want to stay where they are.

How can I detect if a user is scrolled to the bottom of the page or if they have scrolled higher on the page?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Andrew
  • 227,796
  • 193
  • 515
  • 708
  • 1
    This one is worked in Angular 6 --> stackoverflow.com/a/42547136/621951 – Günay Gültekin Oct 11 '18 at 17:16
  • Duplicate of https://stackoverflow.com/questions/3898130 after all – TylerH Mar 03 '23 at 18:41
  • 2
    Does this answer your question? [Check if a user has scrolled to the bottom (not just the window, but any element)](https://stackoverflow.com/questions/3898130/check-if-a-user-has-scrolled-to-the-bottom-not-just-the-window-but-any-element) – pppery Mar 05 '23 at 02:31

23 Answers23

364
window.onscroll = function(ev) {
    if ((window.innerHeight + Math.round(window.scrollY)) >= document.body.offsetHeight) {
        // you're at the bottom of the page
    }
};

See demo

Silver Zachara
  • 2,901
  • 2
  • 16
  • 22
mVChr
  • 49,587
  • 11
  • 107
  • 104
  • Works in all major browsers except IE (my IE version is 11) – Muhamad Jafarnejad Aug 18 '14 at 04:00
  • 52
    Does not work when html/body elements are set to 100% (so that the body fills the entire viewport height) – Grodriguez Oct 23 '14 at 09:47
  • 8
    Use `document.documentElement.scrollTop` instead of `window.scrollY` for IE. Not sure which, if any, versions of IE support `window.scrollY`. – Batandwa Oct 27 '14 at 11:33
  • 3
    Does not work in Chromium Version 47.0.2526.73 Built on Ubuntu 14.04, running on elementary OS 0.3.2 (64-bit) – basickarl Jan 05 '16 at 23:48
  • 12
    I used document.body.scrollHeight instead of offsetHeight (in my case, offsetHeight was always smaller that the window.innerHeight) – Oliver Apr 25 '16 at 11:16
  • 1
    @KarlMorrison can you try the bounty-awarded answer (by @Dekel) with your browser? – Basj Nov 02 '16 at 21:48
  • @Batandwa, `document.documentElement.scrollTop` doesn't work with Safari, but `window.scrollY` does. – Yamashiro Rion Feb 25 '19 at 14:02
  • This appears to be outdated. – Kraken Oct 04 '19 at 13:09
  • Awesome.. It's works too in react-native webview https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#communicating-between-js-and-native – Rudi Wijaya Nov 25 '19 at 15:31
  • Should be : if(Math.ceil(window.innerHeight + window.scrollY) >= document.body.scrollHeight) – london_utku Jan 27 '21 at 22:50
  • Incorrect nowadays, see https://stackoverflow.com/questions/55419779 – trusktr Feb 11 '22 at 20:15
  • In the case, html/body is set to 100% like @Grodriguez mentioned, you can try to check if the
    element is in the viewport. See how I fixed this at: https://deniapps.com/blog/hide-anchor-ads-when-scrolling-to-the-bottom.
    – Adam Cai Nov 06 '22 at 12:49
  • For modern browsers, use documentElement's scroll height, which would be root html tag, instead of body's offset height or scroll height. `(window.innerHeight + window.scrollY) >= document.documentElement.scrollHeight` – Caleb Taylor Jan 26 '23 at 02:38
159

Updated code for all major browsers support (include IE10 & IE11)

window.onscroll = function(ev) {
    if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) {
        alert("you're at the bottom of the page");
    }
};

The problem with the current accepted answer is that window.scrollY is not available in IE.

Here is a quote from mdn regarding scrollY:

For cross-browser compatibility, use window.pageYOffset instead of window.scrollY.

And a working snippet:

window.onscroll = function(ev) {
    if ((window.innerHeight + window.pageYOffset ) >= document.body.offsetHeight) {
        alert("you're at the bottom of the page");
    }
};
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

Note for mac

Based on @Raphaël's comment, there was a problem in mac due to a small offset.
The following updated condition works:

(window.innerHeight + window.pageYOffset) >= document.body.offsetHeight - 2

I didn't have the chance to test it further, if someone can comment about this specific issue it will be great.

Community
  • 1
  • 1
Dekel
  • 60,707
  • 10
  • 101
  • 129
  • Confirmed working on FF, Chrome, IE10, Chrome for Android. Thank you @Dekel! – Basj Nov 02 '16 at 20:40
  • +1 Well done. I have tested this in a broad set of current browsers and have confirmed that it works. The other options do not cover all the browsers. +1 for awarding a bounty to this answer as it emphasizes it as the correct answer. –  Feb 18 '17 at 14:07
  • 3
    Strange as it may sound, only in my browser I am short of 1 px, and hence the condition does not get triggered. Not sure why, had to add extra few px to make it work. – Sharjeel Ahmed Apr 27 '17 at 11:34
  • 6
    on mac computers, the condition below isn't met because of a small offset (~1px) we updated the condition like so `(window.innerHeight + window.pageYOffset) >= document.body.offsetHeight - 2` – Raphaël Jun 20 '17 at 16:55
  • @Raphaël thanks for the comment, I updated the answer accordingly. – Dekel Jun 20 '17 at 17:19
  • 4
    thx @Dekel ! actually, we find out that window.pageYOffset is a float on mac. Our final solution is `(window.innerHeight + Math.ceil(window.pageYOffset + 1)) >= document.body.offsetHeight`. – Raphaël Jun 21 '17 at 13:46
  • Can run into trouble when users change the zoom level in their browser. Can resolve with the following: `Math.ceil(window.innerHeight + window.pageYOffset) >= document.body.offsetHeight` – Matthew Bowen Aug 14 '18 at 01:26
  • 2
    Doesn't work for cases where the body has a style that sets the height to 100% – Jón Trausti Arason Sep 25 '18 at 17:36
  • Sorry I should have been more specific, the html also needs to have 100% height. Working example: https://jsfiddle.net/jontrausti/qd95vcf3/ – Jón Trausti Arason Sep 26 '18 at 08:16
  • 1
    the comment by @Raphaël saved my sleeps! in mac there's 1 px problem and his comment really helped me solve it!! thanks to you man!! God bless you! – Sjd Nov 18 '21 at 19:22
  • I'm quoting MDN: The pageYOffset property is an alias for the scrollY property: `window.pageYOffset === window.scrollY; // always true` – Silver Zachara Apr 29 '23 at 07:14
90

The accepted answer did not work for me. This did:

window.onscroll = function(ev) {
    if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
      // you're at the bottom of the page
      console.log("Bottom of page");
    }
};

If you're looking to support older browsers (IE9) use the alias window.pageYOffset which has slightly better support.

Lex
  • 4,749
  • 3
  • 45
  • 66
Ryan Knell
  • 6,204
  • 2
  • 40
  • 32
  • 1
    does not work in IE10/11. Check Dekel's answer (http://stackoverflow.com/questions/9439725/javascript-how-to-detect-if-browser-window-is-scrolled-to-bottom#answer-40370876) for IE support. Worked for me – Herr_Schwabullek Dec 14 '16 at 08:41
  • 1
    The other answers triggered the console.log() every time I scrolled, not just when I was at the bottom of the page. This answer worked for me on Chrome. – Defcronyke Sep 24 '17 at 21:00
  • 1
    If you get rid of window.scrollY, which doesn't work in i.e. or edge, this is a decent answer. Replace with: (window.innerHeight + window.pageYOffset) >= document.body.scrollHeight – colemerrick Jan 09 '18 at 09:29
  • This works even when you have the body set to a min-height of 100%. – ToddPadwick Feb 03 '21 at 09:59
35

I was searching for an answer but haven't found an exact one. Here is a pure javascript solution that works with latest Firefox, IE and Chrome at the time of this answer:

// document.body.scrollTop alone should do the job but that actually works only in case of Chrome.
// With IE and Firefox it also works sometimes (seemingly with very simple pages where you have
// only a <pre> or something like that) but I don't know when. This hack seems to work always.
var scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;

// Grodriguez's fix for scrollHeight:
// accounting for cases where html/body are set to height:100%
var scrollHeight = (document.documentElement && document.documentElement.scrollHeight) || document.body.scrollHeight;

// >= is needed because if the horizontal scrollbar is visible then window.innerHeight includes
// it and in that case the left side of the equation is somewhat greater.
var scrolledToBottom = (scrollTop + window.innerHeight) >= scrollHeight;

// As a bonus: how to scroll to the bottom programmatically by keeping the horizontal scrollpos:
// Since window.innerHeight includes the height of the horizontal scrollbar when it is visible
// the correct vertical scrollTop would be
// scrollHeight-window.innerHeight+sizeof(horizontal_scrollbar)
// Since we don't know the visibility/size of the horizontal scrollbar
// we scroll to scrollHeight that exceeds the value of the
// desired scrollTop but it seems to scroll to the bottom with all browsers
// without problems even when the horizontal scrollbar is visible.
var scrollLeft = (document.documentElement && document.documentElement.scrollLeft) || document.body.scrollLeft;
window.scrollTo(scrollLeft, scrollHeight);
pasztorpisti
  • 3,760
  • 1
  • 16
  • 26
  • 4
    This almost worked for me, but I had to use `((document.documentElement && document.documentElement.scrollHeight) || document.body.scrollHeight)` instead of just `document.body.scrollHeight` to account for cases where html/body are set to height:100% – Grodriguez Oct 23 '14 at 09:46
  • Your first comment saved me from meaningless struggle on the Firefox console with `document.body.scrollTop`. Thanks. – thiras Feb 11 '21 at 19:46
  • Excellent answer, this snippet here is just for modern browsers, won't work for IE 11, `const scrolledToBottom = (window.innerHeight + window.scrollY) >= document.documentElement.scrollHeight` – Caleb Taylor Jan 26 '23 at 02:45
32

This works

window.onscroll = function() {

    // @var int totalPageHeight
    var totalPageHeight = document.body.scrollHeight; 

    // @var int scrollPoint
    var scrollPoint = window.scrollY + window.innerHeight;

    // check if we hit the bottom of the page
    if(scrollPoint >= totalPageHeight)
    {
        console.log("at the bottom");
    }
}

If you're looking to support older browsers (IE9) replace window.scrollY with window.pageYOffset

Ifeanyi Amadi
  • 776
  • 5
  • 10
  • 1
    this work with react in 2019. work with body 100% height, worth with html 100% height. work with chrome, safari, firefox, edge. – angry kiwi Sep 07 '19 at 13:07
  • Just a note: naming should be changed - variables should be switched. Because scrollHeight shows the total page height, and totalHeight shows current scroll point, so it's a bit confusing. – Vladimir Marton May 09 '20 at 07:37
8

If you're setting height: 100% on some container <div id="wrapper">, then the following code works (tested in Chrome):

var wrapper = document.getElementById('wrapper');

wrapper.onscroll = function (evt) {
  if (wrapper.scrollTop + window.innerHeight >= wrapper.scrollHeight) {
    console.log('reached bottom!');
  }
}
Jeremy Bernier
  • 1,746
  • 1
  • 17
  • 17
6
window.onscroll = function(ev) {
    if ((window.innerHeight + Math.ceil(window.pageYOffset)) >= document.body.offsetHeight) {
        alert("you're at the bottom of the page");
    }
};

This Answer will fix edge cases, this is because pageYOffset is double while innerHeight and offsetHeight are long, so when the browser gives you the info, you may be a pixel short. For example: on bottom of the page we have

true window.innerHeight = 10.2

true window.pageYOffset = 5.4

true document.body.offsetHeight = 15.6

Our calculation then becomes: 10 + 5.4 >= 16 which is false

To fix this we can do Math.ceil on the pageYOffset value.

Hope that helps.

itay yahalom
  • 61
  • 1
  • 4
6

Try this method if you've had no luck with the others.

window.onscroll = function() {
    const difference = document.documentElement.scrollHeight - window.innerHeight;
    const scrollposition = document.documentElement.scrollTop; 
    if (difference - scrollposition <= 2) {
        alert("Bottom of Page!"); 
    }   
}
Darshna Rekha
  • 1,069
  • 7
  • 20
Farid
  • 61
  • 1
  • 1
5

I've just started looking at this and the answers here helped me, so thanks for that. I've expanded a little so that the code is safe all the way back to IE7:

Hope this proves useful for someone.

Here, have a Fiddle ;)

    <!DOCTYPE html>
<html>
<head>
    <style>
        div {
            height: 100px;
            border-bottom: 1px solid #ddd;
        }

        div:nth-child(even) {
            background: #CCC
        }

        div:nth-child(odd) {
            background: #FFF
        }

    </style>
</head>

<body>
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
<div></div><div></div><div></div><div></div><div></div><div></div><div></div>
</body>

<script type="text/javascript">
console.log("Doc Height = " + document.body.offsetHeight);
console.log("win Height = " + document.documentElement.clientHeight);
window.onscroll = function (ev) {
    var docHeight = document.body.offsetHeight;
    docHeight = docHeight == undefined ? window.document.documentElement.scrollHeight : docHeight;

    var winheight = window.innerHeight;
    winheight = winheight == undefined ? document.documentElement.clientHeight : winheight;

    var scrollpoint = window.scrollY;
    scrollpoint = scrollpoint == undefined ? window.document.documentElement.scrollTop : scrollpoint;

    if ((scrollpoint + winheight) >= docHeight) {
        alert("you're at the bottom");
    }
};
</script>
</html>
Craig Poole
  • 740
  • 8
  • 19
  • Sort of works. But it is not very accurate. It considers that it is scrolled to the bottom as long as you are within around 16px of the bottom. – Peter Hall Jan 05 '16 at 01:20
4

New solution.

One issue stems from a lack of a standard main scrolling element. Recently implemented document.scrollingElement can be used to attempt to overcome this. Below is a cross-browser solution with fallback:

function atEnd() {
    var c = [document.scrollingElement.scrollHeight, document.body.scrollHeight, document.body.offsetHeight].sort(function(a,b){return b-a}) // select longest candidate for scrollable length
    return (window.innerHeight + window.scrollY + 2 >= c[0]) // compare with scroll position + some give
}
function scrolling() {
    if (atEnd()) 
        //do something
}
window.addEventListener('scroll', scrolling, {passive: true});
CheeseFrog
  • 49
  • 2
4

The simplest way using vanilla javascript

container.addEventListener('scroll', (e) => {
  var element = e.target;
  if (element.scrollHeight - element.scrollTop - element.clientHeight <= 0) {
    console.log('scrolled to bottom');
  }
});
Derek Dawson
  • 502
  • 5
  • 14
3
$(document).ready(function(){
    $('.NameOfYourDiv').on('scroll',chk_scroll);
});

function chk_scroll(e)
{
    var elem = $(e.currentTarget);
    if (elem[0].scrollHeight - elem.scrollTop() == elem.outerHeight()) 
    {
        alert("scrolled to the bottom");
    }

}
3

if you love jquery

$(window).scroll(function() {
  if($(window).scrollTop() + $(window).height() >= $(document).height()) {
    // doSomethingHere();
  }
});
Eka putra
  • 739
  • 10
  • 15
3

Using defaultView and documentElement with functional code snippet embedded:

const { defaultView } = document;
const { documentElement } = document;
const handler = evt => requestAnimationFrame(() => {
  const hitBottom = (() => (defaultView.innerHeight + defaultView.pageYOffset) >= documentElement.offsetHeight)();
  hitBottom
    ? console.log('yep')
    : console.log('nope')
});
document.addEventListener('scroll', handler);
<pre style="height:110vh;background-color:fuchsia">scroll down</pre>
vhs
  • 9,316
  • 3
  • 66
  • 70
3
const handleScroll = () => {
    if (Math.round(window.scrollY + window.innerHeight) >= Math.round(document.body.scrollHeight)) {
        onScroll();
    }
};

This code worked for me in Firefox and IE as well.

cnnr
  • 1,267
  • 4
  • 18
  • 23
3

As above mentioned code may not work on all the devices and browsers. Below is the tested working code that will compatible with all the major devices (iPhone, Android, PC) in all the browsers (Chrome, IE, Edge, Firefox, and Safari).

window.onscroll = function(ev) {
    var pageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight,  document.documentElement.clientHeight,  document.documentElement.scrollHeight,  document.documentElement.offsetHeight );
    if ((window.innerHeight + window.scrollY) >= pageHeight) {
        console.log("You are at the bottom of the page.");
    }
};
<html>
<body>
  <div style="width:100%; height:1500px">
    <p>Keep scrolling the page till end...</p>
  </div>
</body>
</html>
Possible 11
  • 47
  • 1
  • 3
  • window.innerHeight + window.scrollY might give a result with decimal place, I wrapped it with Math.ceil(window.innerHeight + window.scrollY) – Victor Kwok Sep 07 '22 at 03:45
2

I made this function for Mobile Devices and Desktop try it, It's work for me some of comment here is not working on Mobile/Android devices, BTW Thank You for this question. Keep it Up coders!

    window.addEventListener("scroll", function(el) {
    const scrollY = window.scrollY + window.innerHeight + 2;
    const bodyScroll = document.body.offsetHeight;

    console.log("Scroll Y : " + scrollY);
    console.log("Body : " + bodyScroll);

    if(scrollY >= bodyScroll){
      alert("Bottom Page");
    }
  })
1

Surprisingly none of the solutions worked for me. I think it's because my css was messed up, and body didn't wrap around all of the content when using height: 100% (don't know why yet). However while looking for a solution I've came up with something well... basically the same, but maybe it's worth to look at - I'm new into programming so sorry if it's doing the same slower, is less supported or something like that...

window.onscroll = function(evt) {
  var check = (Element.getBoundingClientRect().bottom - window.innerHeight) <= 0;
  
  if (check) { console.log("You're at the bottom!"); }
};
SRack
  • 11,495
  • 5
  • 47
  • 60
Coldark
  • 445
  • 4
  • 16
1

You can check if the combined result of the window's height and scroll top is bigger than that of the body

if (window.innerHeight + window.scrollY >= document.body.scrollHeight) {}

Oussama Essamadi
  • 358
  • 8
  • 15
1

Two solutions I found that worked for me:

  window.addEventListener('scroll', function(e) {
    if (
      window.innerHeight + document.documentElement.scrollTop ===
      document.documentElement.offsetHeight
    ) {
      console.log('You are at the bottom')
    }
  })

And the other:

  window.addEventListener('scroll', function(e) {
    if (
      window.innerHeight + window.pageYOffset ===
      document.documentElement.offsetHeight
    ) {
      console.log('You are at the bottom')
    }
  })
PJately
  • 477
  • 7
  • 7
  • I think you swapped the term top and bottom. Your solution fired up being at top :-) – m3nda Oct 12 '20 at 14:45
  • Hey @m3nda, Which solution are you referring to? Both seem to fire at the bottom for me... – PJately Oct 13 '20 at 09:20
  • 1
    I tried both of them and where fired when in the top of the page (upper content), opposite to bottom (when you scrolled the full page to it's end). I double checked that in both Chrome and Firefox. Btw, solution of @Ifeanyi Amadi worked as expected. Regards. – m3nda Oct 13 '20 at 17:01
0

This check works ok for me with lazy loading

window.onscroll = () => {
    if (Math.ceil(window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
        alert('Bottom!');
    }
};
Dmytro K.
  • 169
  • 3
  • 5
0

This worked for me note to include the Math.round() function to round off the height to the nearest integer.

window.addEventListener('scroll', function(e) {

    if (Math.round(window.innerHeight + window.scrollY) >= document.body.scrollHeight) {
        alert('bottom');

    }
});
-1

I simply place a small image at the bottom of my page with loading="lazy" so the browser is only loading it when the user scrolls down. The image then trigers a php counter script which returns a real image

 <img loading="lazy" src="zaehler_seitenende.php?rand=<?=rand(1,1000);?>">

 <?php
 @header("Location: https://domain.de/4trpx.gif");
human
  • 467
  • 4
  • 6