Check if a user has scrolled to the bottom (not just the window, but any element)
JavascriptJqueryScrollPaginationJavascript Problem Overview
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. Any ideas?
I'm using jQuery, so feel free to provide answers that use it.
Javascript Solutions
Solution 1 - Javascript
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.
Solution 2 - Javascript
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.
Solution 3 - Javascript
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!");
}
});
Solution 4 - Javascript
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);
}
Solution 5 - Javascript
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
Solution 6 - Javascript
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
.
Solution 7 - Javascript
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
Solution 8 - Javascript
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.
Solution 9 - Javascript
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.
Solution 10 - Javascript
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');
}
});
Solution 11 - Javascript
Here is a vanilla JavaScript solution that uses ES 6 and debounce
:
document.addEventListener('scroll', debounce(() => {
if(document.documentElement.scrollHeight === window.pageYOffset + window.innerHeight) {
// Do something
}
}, 500))
function debounce(e,t=300){let u;return(...i)=>{clearTimeout(u),u=setTimeout(()=>{e.apply(this,i)},t)}}
Demo: https://jsbin.com/jicikaruta/1/edit?js,output
References:
Solution 12 - Javascript
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>
Solution 13 - Javascript
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>
Solution 14 - Javascript
In case someone wants a vanilla JavaScript solution and needs to detect when a user has scrolled to the bottom of a <div>
I managed to implement it by using these lines of code
window.addEventListener("scroll", () => {
var offset = element.getBoundingClientRect().top - element.offsetParent.getBoundingClientRect().top;
const top = window.pageYOffset + window.innerHeight - offset;
if (top === element.scrollHeight) {
console.log("bottom");
}
}, { passive: false });
Solution 15 - Javascript
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");
}
Solution 16 - Javascript
I Have done this very easy way with pure JS.
function onScroll() {
if (window.pageYOffset + window.innerHeight >= document.documentElement.scrollHeight - 50) {
Console.log('Reached bottom')
}
}
window.addEventListener("scroll", onScroll);
Solution 17 - Javascript
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!");
}
});
Solution 18 - Javascript
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');
}
});
Solution 19 - Javascript
Try this for match condition if scroll to bottom end
if ($(this)[0].scrollHeight - $(this).scrollTop() ==
$(this).outerHeight()) {
//code for your custom logic
}
Solution 20 - Javascript
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
}
Solution 21 - Javascript
Here's my two cents as the accepted answer didn't work for me.
var documentAtBottom = (document.documentElement.scrollTop + window.innerHeight) >= document.documentElement.scrollHeight;
Solution 22 - Javascript
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!");
}
Solution 23 - Javascript
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!');
}
});
Solution 24 - Javascript
i used this test to detect the scroll reached the bottom:
event.target.scrollTop === event.target.scrollHeight - event.target.offsetHeight
Solution 25 - Javascript
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
Solution 26 - Javascript
Here is the most simple way to do it:
const handleScroll = () => {
if (window.innerHeight + window.pageYOffset >= document.body.offsetHeight) {
console.log('scrolled to the bottom')
}}
window.addEventListener('scroll', handleScroll)
Solution 27 - Javascript
(2021)
Lots of answers here involve a ref to an element
, but if you only care about the whole page, just use:
function isBottom() {
const { scrollHeight, scrollTop, clientHeight } = document.documentElement;
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
return distanceFromBottom < 20; // adjust the number 20 yourself
}
Solution 28 - Javascript
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"; }
Solution 29 - Javascript
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();
}
}
}
Solution 30 - Javascript
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!");
}
});
}
Solution 31 - Javascript
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
}
});