714

I'm making a pagination system (sort of like Facebook) where the content loads when the user scrolls to the bottom. I imagine the best way to do that is to find when the user is at the bottom of the page and run an ajax query to load more posts.

The only problem is I don't know how to check if the user has scrolled to the bottom of the page with jQuery. Any ideas?

I need to find a way to check when the user has scrolled to the bottom of the page with jQuery.

Thomas Orlita
  • 1,320
  • 13
  • 24
Johnny
  • 8,590
  • 5
  • 24
  • 33
  • That's funny, I'm trying to figure out which function is being called when I scroll to the bottom, so I can block this infuriating "feature". – endolith Jul 03 '18 at 16:08
  • For a React.js solution, this link might help: https://stackoverflow.com/a/53158893/4265546 – raksheetbhat Feb 28 '19 at 13:29

28 Answers28

1074

Use the .scroll() event on window, like this:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() == $(document).height()) {
       alert("bottom!");
   }
});

You can test it here, this takes the top scroll of the window, so how much it's scrolled down, adds the height of the visible window and checks if that equals the height of the overall content (document). If you wanted to instead check if the user is near the bottom, it'd look something like this:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       alert("near bottom!");
   }
});

You can test that version here, just adjust that 100 to whatever pixel from the bottom you want to trigger on.

Nick Craver
  • 594,859
  • 130
  • 1,270
  • 1,139
  • 34
    As usual you get there before me. Anyway, to the OP, if you have a container of posts, use it's ID instead of "window", also, you might want to change the last .height() to scrollHeight – Christian Oct 09 '10 at 22:40
  • 4
    Firefox calls alert("bottom!"); many times (works fine with chrome and safari) – MataMix Aug 13 '12 at 14:09
  • 3
    it's kinda buggy, if you do a `console.log()` instead of alert it sometimes repeats the command. – Jürgen Paul Aug 27 '12 at 12:37
  • 1
    @Nick Craver This fails in iPhone, iPad any idea why? Though works as a charm in all browsers except the above. – LoneWOLFs Jul 05 '13 at 12:35
  • Hey there is bug, :/ This only works when I scroll all the way to bottom and then start scrolling upwards! Otherwise, it doesnot work. I mean if I try to scroll it just the way I should, it shows no alert! I have to touch the bottom and start reaching up! – Afzaal Ahmad Zeeshan Sep 23 '13 at 09:48
  • 1
    TIP: the second option works perfectly on mobile. The first does not. – Liko Sep 28 '13 at 20:07
  • 20
    @KevinVella Vella good combination is to use this with _.debounce() in underscore utility to prevent it firing until user has stopped scrolling - http://underscorejs.org/#debounce - – JohnnyFaldo Feb 10 '14 at 11:27
  • How can we check if we are scrolling back up? Because I get the alert even when I am scrolling up which I don't want. – Si8 Feb 20 '14 at 21:16
  • @Nick I'm trying to create a fixed sidebar that gets a `bottom` class added when it reaches the bottom of its container. Would I be able to alter this code somehow for this function to work? My question is here if you'd like to take a look: http://stackoverflow.com/questions/22571739/how-could-i-add-a-class-of-bottom-to-sidebar-once-it-reaches-the-bottom-of/22572083?noredirect=1#comment34370001_22572083 – J82 Mar 23 '14 at 01:00
  • 1
    @SiKni8 I assume you're doing the "near bottom", either way, store `$(window).scrollTop()` as a variable, if it's less than last time, you're scrolling up. – Nick Craver Mar 23 '14 at 13:41
  • @Desi If you want to know when your container bottom hits page bottom, just subtract your container's `.position().top` instead of the 100 above. – Nick Craver Mar 23 '14 at 13:43
  • @NickCraver do you have any idea on this problem that I have with your solution? the first part doesn't work because I can't have a strict equality: http://stackoverflow.com/questions/22867584/get-scroll-percentage-in-a-dom-container – Sebastien Lorber Apr 04 '14 at 16:00
  • Use a trottle function for performance, E.G. http://benalman.com/projects/jquery-throttle-debounce-plugin/ – Jacob van Lingen Apr 14 '14 at 08:01
  • If you have issues getting the real document height using $(document).height(), you can use e.target.scrollHeight where e is the scroll event. – Tmac May 01 '14 at 15:30
  • 1
    The solution is not working for iPad device for Landscape mode .. but it works fine with portrait mode. – Ashwin Hegde Jan 16 '15 at 14:36
  • 3
    @NickCraver is there any pure js implementation available? – Dewsworld Jun 21 '15 at 07:08
  • @NickCraver Thanks for the Answer. But Your solution is not worked for me. Hv changed window.innerHeight instead of $(window).height() is gives me what i want. – Jothi Sankar N Kanakavel Oct 10 '15 at 08:44
  • 1
    Not sure if it's a general browser problem, adding Math.round($(window).scrollTop() + $(window).height()) is needed for Chrome to make sure scroll to bottom detected in different zoom levels – Ivan Li Sep 15 '16 at 12:06
  • `$(window).scrollTop()` is not always integer value when tested in Chrome. To fix that you can use: `Math.floor($(window).scrollTop() + $(window).height()) == $(document).height()` – jcubic Dec 09 '16 at 18:17
  • This does not work with jquery 2.2.4. Any ideas why and how to do it with jquery 2.2.4? – Tadej Dec 20 '16 at 10:58
  • 1
    for some reason its not working anymore on chorme, this is what I get when using console.log 912.5999755859375 == 913 at the end of the document... – Diogo Garcia Jul 20 '17 at 12:48
  • 1
    This triggers the event when the user scrolls to the top of the page..not to the bottem – Afghan Dev Aug 24 '17 at 10:13
  • 2
    This used to work good, but now I have a problem on 1920 * 1080 screens – Reza Nov 03 '18 at 19:39
  • 1
    If this isn't working for you, try adding . It worked on Chrome only after adding that. [See thislink](https://stackoverflow.com/questions/12103208/jquery-window-height-is-returning-the-document-height). – Andrew Lim Nov 04 '18 at 01:06
  • To check whether the page is close to scrolling all the way sideways to the right, I modified the code to read like this: if ($(window).scrollLeft() + $(window).width() > $(document).width() - 100) {...} – LauraNMS Nov 22 '19 at 15:07
  • You might consider using Math.ceil($(window).scrollTop()), otherwise the desired "bottom" might not be reached! – Wilhelm Sorban Nov 11 '20 at 19:20
  • A coworker copied from here and during UAT a tester with default 110% zoom cannot get the table to load more data. Turns out those numbers can be of fractional pixels with zooming is in effect. – T Tse Jan 12 '21 at 07:58
135

I'm not exactly sure why this has not been posted yet, but as per the documentation from MDN, the simplest way is by using native javascript properties:

element.scrollHeight - element.scrollTop === element.clientHeight

Returns true when you're at the bottom of any scrollable element. So simply using javascript:

element.addEventListener('scroll', function(event)
{
    var element = event.target;
    if (element.scrollHeight - element.scrollTop === element.clientHeight)
    {
        console.log('scrolled');
    }
});

scrollHeight have wide support in browsers, from ie 8 to be more precise, while clientHeight and scrollTop are both supported by everyone. Even ie 6. This should be cross browser safe.

Félix Gagnon-Grenier
  • 7,344
  • 10
  • 45
  • 58
  • 1
    Note that in some situations this may not be the case. Firefox 47 reports a textarea clientHeight as 239 while the above equation gives 253 when scrolled to the bottom. Maybe padding/border or something is affecting it? Either way, adding some wiggle room wouldn't hurt, like `var isAtBottom = ( logField.scrollHeight - logField.scrollTop <= logField.clientHeight + 50 );`. This is useful for auto-scrolling a field only if already at the bottom (so the user can manually examine a specific part of a realtime log without losing their place, etc). – Beejor Aug 19 '16 at 09:30
  • I would add that it's possible for it to return false negatives as one side could return a small decimal while the other side returns a whole number (eg. `200.181819304947` and `200`). I added a `Math.floor()` to help deal with that but I don't know how reliable this will be. – Hanna Nov 07 '16 at 22:44
  • 1
    For me, this doesn't work cross browser. I get completely different results on chrome compared to firefox. – Tadej Dec 20 '16 at 13:45
  • 1
    I tried this on the element, and this is firing when the browser is scrolled to the TOP, not the bottom. – Chris Sobolewski Jan 31 '17 at 16:07
  • @ChrisSobolewski I must admit I haven't tested on the body element. would you happen to have a fiddle with the issue? I'm positive it definitely works at the bottom of the elements I'm using this on. – Félix Gagnon-Grenier Feb 01 '17 at 04:32
  • 17
    `Math.abs(element.scrollHeight - element.scrollTop - element.clientHeight) <= 3.0` (replace 3.0 with whatever pixel tolerance you think is appropriate for your circumstances). This is the way to go because (A) `clientHeight`, `scrollTop`, and `clientHeight` are all rounded which could potentially lead to a 3px error if all align, (B) 3 pixels is hardly visible to the user so the user may think something is wrong with your site when they "think" they are at the bottom of the page when in fact they are not, and (C) certain devices (especially mouseless ones) can have odd behavior when scrolling. – Jack Giffin Oct 21 '18 at 18:50
122

Nick Craver's answer works fine, spare the issue that the value of $(document).height() varies by browser.

To make it work on all browsers, use this function from James Padolsey:

function getDocHeight() {
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

in place of $(document).height(), so that the final code is:

$(window).scroll(function() {
       if($(window).scrollTop() + $(window).height() == getDocHeight()) {
           alert("bottom!");
       }
   });
iwasrobbed
  • 45,197
  • 20
  • 140
  • 190
Miles O'Keefe
  • 1,438
  • 1
  • 11
  • 17
  • 7
    He has updated with a slightly compressed version function getDocHeight() { var D = document; return Math.max( D.body.scrollHeight, D.documentElement.scrollHeight, D.body.offsetHeight, D.documentElement.offsetHeight, D.body.clientHeight, D.documentElement.clientHeight ); } – Drew Jul 26 '13 at 14:43
  • that alerts me when I reach the top, not the bottom (Chrome). – Damien Roche Jul 25 '18 at 09:07
  • It might be better to use `min` instead of `max`, especially if there's a margin anyways, to avoid accidentally preventing the user from scrolling to what you think is the bottom of the page. – Solomon Ucko Apr 24 '19 at 13:35
54

For those using Nick's solution and getting repeated alerts / events firing, you could add a line of code above the alert example:

$(window).scroll(function() {
   if($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
       $(window).unbind('scroll');
       alert("near bottom!");
   }
});

This means that the code will only fire the first time you're within 100px of the bottom of the document. It won't repeat if you scroll back up and then back down, which may or may not be useful depending on what you're using Nick's code for.

Tim Carr
  • 739
  • 6
  • 4
  • 1
    I would've just commented and said where that line of code is since its relevant to someone else's answer but +1 for the intention! – Nate-Wilkins Oct 01 '12 at 17:07
  • Sorry, I couldn't (and still can't) see how to add a comment to the answer (like I can here)? – Tim Carr Oct 01 '12 at 19:12
  • Yea new users can't add a comment to posts unless you get more rep. – Nate-Wilkins Oct 01 '12 at 21:12
  • Out side the first if you could put a different if that tests if the change you wanted the script to make exists, say a class having been applied to a div. This would make the second nested if not run if it has already run. – 1934286 Jan 31 '13 at 09:06
  • how can i select particular div id instead of the whole window? – James Smith Mar 23 '15 at 03:28
  • some day ago i am facing this type of problem.i using ajax call when page scroll .when i scroll the page continuously request send to server. after reading your this answer i understood using `$(window).unbind('scroll');` line problem will be solved. – Sk Asraf Jun 24 '16 at 21:10
  • `$(document).height() - 100` is key, I ended up changing it too 50. For some reason, sometimes adding browser extensions or antivirus stuff changes the value of the screen so better too just leave a little margin for a lazy load to work. – Roberto Ibarra Rabadán Feb 24 '21 at 21:28
40

Further to the excellent accepted answer from Nick Craver, you can throttle the scroll event so that it is not fired so frequently thus increasing browser performance:

var _throttleTimer = null;
var _throttleDelay = 100;
var $window = $(window);
var $document = $(document);

$document.ready(function () {

    $window
        .off('scroll', ScrollHandler)
        .on('scroll', ScrollHandler);

});

function ScrollHandler(e) {
    //throttle event:
    clearTimeout(_throttleTimer);
    _throttleTimer = setTimeout(function () {
        console.log('scroll');

        //do work
        if ($window.scrollTop() + $window.height() > $document.height() - 100) {
            alert("near bottom!");
        }

    }, _throttleDelay);
}
George Filippakos
  • 14,863
  • 12
  • 75
  • 86
  • It should probably be pointed out that this requires Underscore.js: http://underscorejs.org/. It's a very good point, though. The scroll event should pretty much always be throttled to avoid serious performance issues. – Jude Osborn Jun 18 '13 at 08:21
  • Maybe it's just me and it could use some benchmarking, but I don't like the idea of invoking clearTimeout and setTimeout on every scroll event. I would issue 1 setTimeout and add some guards in that handler. It's probably just a micro-optimization (if at all). – Grimace of Despair Sep 16 '13 at 14:31
  • This is a really neat addition! I can think of one further improvement . Currently the function that checks the height wont run if the user continues to scroll. If this is a problem (e.g. you want to trigger the function when the user scrolled half way down regardless of if they keep scrolling) you can easily make sure that the function actually gets called while still prohibiting multiple calls during the chosen interval. Here is a gist to show it. https://gist.github.com/datacarl/7029558 – datacarl Oct 17 '13 at 18:16
  • What? Invoke a load of machinery to prevent a simple calculation? I don't see how that is more efficient at all – Rambatino Nov 26 '17 at 10:14
37

Nick Craver's answer needs to be slightly modified to work on iOS 6 Safari Mobile and should be:

$(window).scroll(function() {
   if($(window).scrollTop() + window.innerHeight == $(document).height()) {
       alert("bottom!");
   }
});

Changing $(window).height() to window.innerHeight should be done because when the address bar is hidden an additional 60px are added to the window's height but using $(window).height() does not reflect this change, while using window.innerHeight does.

Note: The window.innerHeight property also includes the horizontal scrollbar's height (if it is rendered), unlike $(window).height() which will not include the horizontal scrollbar's height. This is not a problem in Mobile Safari, but could cause unexpected behavior in other browsers or future versions of Mobile Safari. Changing == to >= could fix this for most common use cases.

Read more about the window.innerHeight property here

Liam
  • 22,818
  • 25
  • 93
  • 157
BlueYoshi
  • 1,128
  • 10
  • 18
25

Here's a fairly simple approach

const didScrollToBottom = elm.scrollTop + elm.clientHeight == elm.scrollHeight

Example

elm.onscroll = function() {
    if(elm.scrollTop + elm.clientHeight == elm.scrollHeight) {
        // User has scrolled to the bottom of the element
    }
}

Where elm is an element retrieved from i.e document.getElementById.

Frederik Witte
  • 868
  • 1
  • 15
  • 29
  • it used to work for me , but don't know due to browser update or something , it is getting missed by few decimals like ```value1 : 1200.1111450195312 value2 : 1200``` – MOHANTEJA Nov 09 '20 at 12:51
18

Please check this answer

 window.onscroll = function(ev) {
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
       console.log("bottom");
    }
};

You can do footerHeight - document.body.offsetHeight to see if you are near the footer or reached the footer

Community
  • 1
  • 1
Junaid Qadir Shekhanzai
  • 1,287
  • 1
  • 18
  • 34
17

Here is a piece of code that will help you debug your code, I tested the above answers and found them to be buggy. I have test the followings on Chrome, IE, Firefox, IPad(Safari). I don't have any others installed to test...

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var winElement = $(window)[0];

         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
            alert('bottom');
         }
      });
   });
</script>

There may be a simpler solution, but I stopped at the point at which IT WORKED

If you are still having problems with some rogue browser, here is some code to help you debug:

<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var details = "";
         details += '<b>Document</b><br />';
         details += 'clientHeight:' + docElement.clientHeight + '<br />';
         details += 'clientTop:' + docElement.clientTop + '<br />';
         details += 'offsetHeight:' + docElement.offsetHeight + '<br />';
         details += 'offsetParent:' + (docElement.offsetParent == null) + '<br />';
         details += 'scrollHeight:' + docElement.scrollHeight + '<br />';
         details += 'scrollTop:' + docElement.scrollTop + '<br />';

         var winElement = $(window)[0];
         details += '<b>Window</b><br />';
         details += 'innerHeight:' + winElement.innerHeight + '<br />';
         details += 'outerHeight:' + winElement.outerHeight + '<br />';
         details += 'pageYOffset:' + winElement.pageYOffset + '<br />';
         details += 'screenTop:' + winElement.screenTop + '<br />';
         details += 'screenY:' + winElement.screenY + '<br />';
         details += 'scrollY:' + winElement.scrollY + '<br />';

         details += '<b>End of page</b><br />';
         details += 'Test:' + (docElement.scrollHeight - winElement.innerHeight) + '=' + winElement.pageYOffset + '<br />';
         details += 'End of Page? ';
         if ((docElement.scrollHeight - winElement.innerHeight) == winElement.pageYOffset) {
             details += 'YES';
         } else {
             details += 'NO';
         }

         $('#test').html(details);
      });
   });
</script>
<div id="test" style="position: fixed; left:0; top: 0; z-index: 9999; background-color: #FFFFFF;">

I hope this will save someone some time.

Peter Hall
  • 36,534
  • 10
  • 79
  • 144
Talon
  • 3,263
  • 3
  • 28
  • 44
11

This is my two cents:

$('#container_element').scroll( function(){
        console.log($(this).scrollTop()+' + '+ $(this).height()+' = '+ ($(this).scrollTop() + $(this).height())   +' _ '+ $(this)[0].scrollHeight  );
        if($(this).scrollTop() + $(this).height() == $(this)[0].scrollHeight){
            console.log('bottom found');
        }
    });
ddanone
  • 469
  • 4
  • 7
  • 1
    Tried yo use your solution, it works fine but in the cases when element has padding - it doesn't work because it calculates pure height of element, without including of padding, to solve this I changed this `$(this).scrollTop() + $(this).height() == $(this)[0].scrollHeight` => `$(this).scrollTop() + $(this).outerHeight(true) >= $(this)[0].scrollHeight` – Taras Chernata Dec 21 '19 at 14:25
11
var elemScrolPosition = elem.scrollHeight - elem.scrollTop - elem.clientHeight;

It calculates distance scroll bar to bottom of element. Equal 0, if scroll bar has reached bottom.

Vasyl Gutnyk
  • 4,153
  • 2
  • 29
  • 35
  • 1
    I did the following and worked flawlessly. Thanks. var shouldScroll = (elem.scrollHeight - elem.scrollTop - elem.clientHeight) == 0; – jiminssy Nov 20 '16 at 16:48
6

Pure JS with cross-browser and debouncing (Pretty good performance)

var CheckIfScrollBottom = debouncer(function() {
    if(getDocHeight() == getScrollXY()[1] + window.innerHeight) {
       console.log('Bottom!');
    }
},500);

document.addEventListener('scroll',CheckIfScrollBottom);

function debouncer(a,b,c){var d;return function(){var e=this,f=arguments,g=function(){d=null,c||a.apply(e,f)},h=c&&!d;clearTimeout(d),d=setTimeout(g,b),h&&a.apply(e,f)}}
function getScrollXY(){var a=0,b=0;return"number"==typeof window.pageYOffset?(b=window.pageYOffset,a=window.pageXOffset):document.body&&(document.body.scrollLeft||document.body.scrollTop)?(b=document.body.scrollTop,a=document.body.scrollLeft):document.documentElement&&(document.documentElement.scrollLeft||document.documentElement.scrollTop)&&(b=document.documentElement.scrollTop,a=document.documentElement.scrollLeft),[a,b]}
function getDocHeight(){var a=document;return Math.max(a.body.scrollHeight,a.documentElement.scrollHeight,a.body.offsetHeight,a.documentElement.offsetHeight,a.body.clientHeight,a.documentElement.clientHeight)}

Demo : http://jsbin.com/geherovena/edit?js,output

PS: Debouncer, getScrollXY, getDocHeight not written by me

I just show how its work, And how I will do

l2aelba
  • 18,585
  • 20
  • 90
  • 131
6

My solution in plain js:

let el=document.getElementById('el');
el.addEventListener('scroll', function(e) {
    if (this.scrollHeight - this.scrollTop - this.clientHeight<=0) {
        alert('Bottom');
    }
});
#el{
  width:400px;
  height:100px;
  overflow-y:scroll;
}
<div id="el">
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
</div>
Fay Boisam
  • 97
  • 1
  • 8
Bakos Bence
  • 187
  • 4
  • 6
4

Try this for match condition if scroll to bottom end

if ($(this)[0].scrollHeight - $(this).scrollTop() == 
    $(this).outerHeight()) {

    //code for your custom logic

}
Jake Freeman
  • 1,706
  • 1
  • 6
  • 15
Hiren Patel
  • 509
  • 4
  • 6
3

Nick answers its fine but you will have functions which repeats itsself while scrolling or will not work at all if user has the window zoomed. I came up with an easy fix just math.round the first height and it works just as assumed.

    if (Math.round($(window).scrollTop()) + $(window).innerHeight() == $(document).height()){
    loadPagination();
    $(".go-up").css("display","block").show("slow");
}
Florin Andrei
  • 217
  • 1
  • 10
3

You can try the following code,

$("#dashboard-scroll").scroll(function(){
    var ele = document.getElementById('dashboard-scroll');
    if(ele.scrollHeight - ele.scrollTop === ele.clientHeight){
       console.log('at the bottom of the scroll');
    }
});
Shahrukh Anwar
  • 2,004
  • 1
  • 18
  • 20
3

Instead of listening to the scroll event, using Intersection Observer is the inexpensive one for checking if the last element was visible on the viewport (that's mean user was scrolled to the bottom). It also supported for IE7 with the polyfill.

var observer = new IntersectionObserver(function(entries){
   if(entries[0].isIntersecting === true)
      console.log("Scrolled to the bottom");
   else
      console.log("Not on the bottom");
}, {
   root:document.querySelector('#scrollContainer'),
   threshold:1 // Trigger only when whole element was visible
});

observer.observe(document.querySelector('#scrollContainer').lastElementChild);
#scrollContainer{
  height: 100px;
  overflow: hidden scroll;
}
<div id="scrollContainer">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
  <div>Item 5</div>
  <div>Item 6</div>
  <div>Item 7</div>
  <div>Item 8</div>
  <div>Item 9</div>
  <div>Item 10</div>
</div>
StefansArya
  • 2,108
  • 3
  • 15
  • 23
  • The problem with Intersection Observer is that if the starting window is relatively small ( say basic layout before fetching images without scrollbar) observer callback is triggered immediately. Scroll listener actually waits for a person to scroll. And scrollbar won't appear before first batch of images and etc. is fetched. So Intersection Observer is not all in one solution. – Aleks Mar 12 '20 at 02:38
  • @Aleks You can call the `.observe(...)` on an event listener like when the user hovering/touching your scroll container so it won't trigger immediately. – StefansArya Mar 12 '20 at 18:32
2

This gives accurate results, when checking on a scrollable element (i.e. not window):

// `element` is a native JS HTMLElement
if ( element.scrollTop == (element.scrollHeight - element.offsetHeight) )
    // Element scrolled to bottom

offsetHeight should give the actual visible height of an element (including padding, margin, and scrollbars), and scrollHeight is the entire height of an element including invisible (overflowed) areas.

jQuery's .outerHeight() should give similar result to JS's .offsetHeight -- the documentation in MDN for offsetHeight is unclear about its cross-browser support. To cover more options, this is more complete:

var offsetHeight = ( container.offsetHeight ? container.offsetHeight : $(container).outerHeight() );
if  ( container.scrollTop == (container.scrollHeight - offsetHeight) ) {
   // scrolled to bottom
}

Yuval A.
  • 5,007
  • 9
  • 47
  • 59
  • try `Math.floor(element.scrollTop) === element.scrollHeight - element.offsetHeight` in case the scrollTop is a decimal it won't work without `Math.floor()` – Michail Michailidis Mar 04 '20 at 10:56
1

All these solutions doesn't work for me on Firefox and Chrome, so I use custom functions from Miles O'Keefe and meder omuraliev like this:

function getDocHeight()
{
    var D = document;
    return Math.max(
        D.body.scrollHeight, D.documentElement.scrollHeight,
        D.body.offsetHeight, D.documentElement.offsetHeight,
        D.body.clientHeight, D.documentElement.clientHeight
    );
}

function getWindowSize()
{
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return [myWidth, myHeight];
}

$(window).scroll(function()
{
    if($(window).scrollTop() + getWindowSize()[1] == getDocHeight())
    {
        alert("bottom!");
    }
});
hayj
  • 710
  • 8
  • 17
1

Here's my two cents as the accepted answer didn't work for me.

var documentAtBottom = (document.documentElement.scrollTop + window.innerHeight) >= document.documentElement.scrollHeight;
alseether
  • 1,837
  • 2
  • 21
  • 37
Razor
  • 16,811
  • 22
  • 87
  • 137
1

Many other solutions doesn't work for me Because on scroll to bottom my div was triggering the alert 2 times and when moving up it was also trigerring upto a few pixels so The solution is:

        $('#your-div').on('resize scroll', function()
        {
            if ($(this).scrollTop() +
                $(this).innerHeight() >=
                $(this)[0].scrollHeight + 10) {

                alert('reached bottom!');
            }
        });
MR_AMDEV
  • 934
  • 1
  • 12
  • 23
0

Let me show approch without JQuery. Simple JS function:

function isVisible(elem) {
  var coords = elem.getBoundingClientRect();
  var topVisible = coords.top > 0 && coords.top < 0;
  var bottomVisible = coords.bottom < shift && coords.bottom > 0;
  return topVisible || bottomVisible;
}

Short example how to use it:

var img = document.getElementById("pic1");
    if (isVisible(img)) { img.style.opacity = "1.00";  }
Alexei Zababurin
  • 656
  • 10
  • 13
  • 5
    This doesn't answer the question. The question was how to detect that the users has scrolled the window all the way to the bottom. Your code is checking if a particular element is in view. – Peter Hall Jan 05 '16 at 18:58
0

I used @ddanone answear and added Ajax call.

$('#mydiv').on('scroll', function(){
  function infiniScroll(this);
});

function infiniScroll(mydiv){
console.log($(mydiv).scrollTop()+' + '+ $(mydiv).height()+' = '+ ($(mydiv).scrollTop() + $(mydiv).height())   +' _ '+ $(mydiv)[0].scrollHeight  );

if($(mydiv).scrollTop() + $(mydiv).height() == $(mydiv)[0].scrollHeight){
    console.log('bottom found');
    if(!$.active){ //if there is no ajax call active ( last ajax call waiting for results ) do again my ajax call
        myAjaxCall();
    }
}

}

Henrique C.
  • 876
  • 1
  • 11
  • 31
0

To stop repeated alert of Nick's answer

ScrollActivate();

function ScrollActivate() {
    $(window).on("scroll", function () {
        if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
            $(window).off("scroll");
            alert("near bottom!");
        }
    });
}
Arun Prasad E S
  • 7,342
  • 6
  • 61
  • 75
0

Google Chrome gives the full height of the page if you call $(window).height()

Instead, use window.innerHeight to retrieve the height of your window. Necessary check should be:

if($(window).scrollTop() + window.innerHeight > $(document).height() - 50) {
    console.log("reached bottom!");
}
alierdogan7
  • 170
  • 2
  • 6
0

Apparently what worked for me was 'body' and not 'window' like this:

$('body').scroll(function() {


 if($('body').scrollTop() + $('body').height() == $(document).height()) {
     //alert at buttom
 }
 });

for cross-browser compatibility use:

  function getheight(){
    var doc = document;
    return  Math.max(
        doc.body.scrollHeight, doc.documentElement.scrollHeight,
        doc.body.offsetHeight, doc.documentElement.offsetHeight,
        doc.body.clientHeight, doc.documentElement.clientHeight

        );
   }

and then instead of $(document).height() call the function getheight()

$('body').scroll(function() {


   if($('body').scrollTop() + $('body').height() == getheight()  ) {
     //alert at bottom
 }
});

for near bottom use:

$('body').scroll(function() {


if($('body').scrollTop() + $('body').height() > getheight() -100 ) {
    //alert near bottom
 }
 });
GeniusGeek
  • 275
  • 3
  • 11
0

i used this test to detect the scroll reached the bottom: event.target.scrollTop === event.target.scrollHeight - event.target.offsetHeight

Dharman
  • 21,838
  • 18
  • 57
  • 107
0

Safari can scroll past the bottom of the page which was causing a bug in our application. Solve this using >= instead of ===.

container.scrollTop >= container.scrollHeight - container.clientHeight
Scott Wager
  • 207
  • 3
  • 4