关于javascript:检查用户是否已滚动到底部

Check if a user has scrolled to the bottom

我正在创建一个分页系统(有点像Facebook),当用户滚动到底部时,内容会加载。 我想最好的方法是找到用户位于页面底部并运行ajax查询以加载更多帖子。

唯一的问题是我不知道如何检查用户是否已使用jQuery滚动到页面底部。 有任何想法吗?

我需要找到一种方法来检查用户何时使用jQuery滚动到页面底部。


window上使用.scroll()事件,如下所示:

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

您可以在此处进行测试,这将采用窗口的顶部滚动,因此向下滚动多少,添加可见窗口的高度并检查它是否等于整个内容的高度(document)。如果你想检查用户是否接近底部,它看起来像这样:

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

您可以在此处测试该版本,只需将100调整为您想要触发的底部的任何像素。


尼克克拉弗的答案很好,除了$(document).height()的价值因浏览器而异。

要使其适用于所有浏览器,请使用James Padolsey的此功能:

1
2
3
4
5
6
7
8
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
    );
}

代替$(document).height(),以便最终代码为:

1
2
3
4
5
$(window).scroll(function() {
       if($(window).scrollTop() + $(window).height() == getDocHeight()) {
           alert("bottom!");
       }
   });


我不确定为什么还没有发布,但根据MDN的文档,最简单的方法是使用本机javascript属性:

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

当您位于任何可滚动元素的底部时,返回true。所以简单地使用javascript:

1
2
3
4
5
6
7
8
element.addEventListener('scroll', function(event)
{
    var element = event.target;
    if (element.scrollHeight - element.scrollTop === element.clientHeight)
    {
        console.log('scrolled');
    }
});

scrollHeight在浏览器中有广泛的支持,从8开始更精确,而clientHeightscrollTop都得到大家的支持。即使是6.这应该是跨浏览器安全的。


对于那些使用Nick的解决方案并获得重复警报/事件触发的人,您可以在警报示例上方添加一行代码:

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

这意味着代码只会在您第一次在文档底部的100px范围内时触发。如果您向上滚动然后向下滚动,它将不会重复,根据您使用的尼克代码,这可能有用也可能没有用。


除了Nick Craver的优秀接受答案之外,您可以限制滚动事件,以便不会频繁触发,从而提高浏览器性能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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);
}


Nick Craver的答案需要稍加修改才能在iOS 6 Safari Mobile上运行,应该是:

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

将$(window).height()更改为window.innerHeight应该完成,因为当隐藏地址栏时,窗口的高度会添加额外的60px,但使用window.innerHeight时,使用window.innerHeight并不会反映此更改。

注意:window.innerHeight属性还包括水平滚动条的高度(如果它被渲染),与$(window).height()不同,它不包括水平滚动条的高度。这在Mobile Safari中不是问题,但可能会在其他浏览器或未来版本的Mobile Safari中导致意外行为。将==更改为>=可以解决大多数常见用例的问题。

在此处阅读有关window.innerHeight属性的更多信息


这是一个相当简单的方法:

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

这是一段代码,可以帮助您调试代码,我测试了上面的答案,发现它们是错误的。我在Chrome,IE,Firefox,iPad(Safari)上测试了以下内容。我没有安装任何其他测试...

1
2
3
4
5
6
7
8
9
10
11
<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');
         }
      });
   });

可能有一个更简单的解决方案,但我停止了IT工作的时间点

如果你仍然遇到一些流氓浏览器的问题,这里有一些代码可以帮你调试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script type="text/javascript">
   $(function() {
      $(window).scroll(function () {
         var docElement = $(document)[0].documentElement;
         var details ="";
         details += 'Document<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 += 'Window<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 += 'End of page<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);
      });
   });

我希望这能节省一些时间。


这是我的两分钱:

1
2
3
4
5
6
$('#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');
        }
    });


1
var elemScrolPosition = elem.scrollHeight - elem.scrollTop - elem.clientHeight;

它计算距离滚动条到元素的底部。
如果滚动条已到达底部,则等于0。


请检查这个答案

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

您可以执行footerHeight - document.body.offsetHeight以查看是否靠近页脚或到达页脚


纯JS与跨浏览器和debouncing(相当不错的性能)

1
2
3
4
5
6
7
8
9
10
11
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)}

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

PS:DebouncergetScrollXYgetDocHeight不是我写的

我只是展示它的工作方式,以及我将如何做


尼克回答它很好,但是你会在滚动时重复自己的功能,或者如果用户有窗口缩放则根本无法工作。我想出了一个简单的解决方法,只需数学。在第一个高度,它就像假设的那样工作。

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

您可以尝试以下代码,

1
2
3
4
5
6
$("#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');
    }
});


如果滚动到底端,请尝试匹配条件

1
2
3
4
5
6
if ($(this)[0].scrollHeight - $(this).scrollTop() ==
    $(this).outerHeight()) {

    //code for your custom logic

}

我在普通js中的解决方案:

1
2
3
4
5
6
let el=document.getElementById('el');
el.addEventListener('scroll', function(e) {
    if (this.scrollHeight - this.scrollTop - this.clientHeight<=0) {
        alert('Bottom');
    }
});
1
2
3
4
5
#el{
  width:400px;
  height:100px;
  overflow-y:scroll;
}
1
2
3
4
5
6
7
8
9
10
11
content
content
content
content
content
content
content
content
content
content
content


所有这些解决方案对我来说都不适用于Firefox和Chrome,所以我使用Miles O'Keefe的自定义函数和meural omuraliev如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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!");
    }
});

当检查可滚动元素(即不是window)时,这会给出准确的结果:

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

offsetHeight应该给出元素的实际可见高度(包括填充,边距和滚动条),scrollHeight是包含不可见(溢出)区域的元素的整个高度。

jQuery.outerHeight()应该给JS的.offsetHeight提供类似的结果 -
MDN for offsetHeight中的文档不清楚其跨浏览器支持。要涵盖更多选项,这是更完整的:

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

如果您拨打$(window).height(),Google Chrome会提供整个页面的高度

而是使用window.innerHeight来检索窗口的高度。
必要的检查应该是:

1
2
3
if($(window).scrollTop() + window.innerHeight > $(document).height() - 50) {
    console.log("reached bottom!");
}


要停止尼克的回答的反复警报

1
2
3
4
5
6
7
8
9
10
ScrollActivate();

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

让我在没有JQuery的情况下展示approch。简单的JS功能:

1
2
3
4
5
6
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;
}

简短示例如何使用它:

1
2
var img = document.getElementById("pic1");
    if (isVisible(img)) { img.style.opacity ="1.00";  }


我使用@ddanone answear并添加了Ajax调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
$('#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();
    }
}

}


这是我的两分钱,因为接受的答案对我不起作用。

1
var documentAtBottom = (document.documentElement.scrollTop + window.innerHeight) >= document.documentElement.scrollHeight;