检查用户是否滚动到底部(不仅仅是窗口,而是任何元素)

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

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

我正在使用jQuery,所以请随时提供使用它的答案。

731372 次浏览

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

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

你可以在这里测试,这需要窗口的顶部滚动,所以它向下滚动了多少,添加可见窗口的高度并检查这是否等于整体内容的高度(document)。如果你想检查用户是否是附近底部,它看起来像这样:

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

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

Nick Craver的回答很有效,避免了$(document).height()的值因浏览器而异的问题。

要使其适用于所有浏览器,请使用詹姆斯·帕多尔西中的此函数:

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(),因此最终代码为:

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

除了Nick Craver的优秀回答之外,您还可以限制滚动事件,使其不会频繁触发,因此提高浏览器性能

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的回答需要稍微修改以适用于iOS6SafariMobile,应该是:

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

应该将$(窗口)。高度()更改为window.inner高度,因为当隐藏地址栏时,窗口的高度会增加60像素,但使用$(window).height()没有会反映此更改,而使用window.innerHeight则会。

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

阅读更多关于window.innerHeight属性这里

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

<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>

可能有一个更简单的解决方案,但我停在了起作用了

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

<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;">

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

让我展示一下没有JQuery的方法。简单的JS函数:

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;
}

简单的例子如何使用它:

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

这是一个使用ES 6和debounce的普通JavaScript解决方案:

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)}}

演示:https://jsbin.com/jicikaruta/1/edit?js,输出

参考文献:

这是我的两分钱:

$('#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');
}
});

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

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

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

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

scrollHeight在浏览器中有广泛的支持,从ie 8更准确地说,而clientHeightscrollTop都受到每个人的支持。即使是ie 6。这应该是跨浏览器安全的。

请检查这个答案

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

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

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

$('#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();
}
}

}

这里有一个相当简单的方法

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

示例

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

其中elm是从document.getElementById中检索的元素。

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

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

为了阻止尼克的回答反复提醒

ScrollActivate();


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

尼克回答它的罚款,但你将有重复的功能,而滚动或将不工作,如果用户有窗口缩放。我想出了一个简单的修复只是math.round第一个高度,它的工作原理就像假设。

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

所有这些解决方案都不适用于Firefox和Chrome,所以我使用MilesO'Keefemederomuraliev中的自定义函数,如下所示:

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!");
}
});

您可以尝试以下代码,

$("#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');
}
});

我在纯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>

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

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


//code for your custom logic


}

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

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

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

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

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

jQuery.outerHeight()应该给出与JS的.offsetHeight类似的结果-- offsetHeight的MDN留档不清楚它的跨浏览器支持。为了涵盖更多选项,这更完整:

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


如果您调用$(window).height(),GoogleChrome会给出页面的完整高度

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

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

而不是监听滚动事件,使用交叉点观察者便宜来检查最后一个元素是否在视口上可见(这意味着用户被滚动到底部)。它还支持带有聚填充的IE7。

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>

显然,对我有效的是“身体”,而不是像这样的“窗口”:

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




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

对于跨浏览器兼容性使用:

  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


);
}

然后调用函数getheight()而不是$(documents).高度()

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




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

近底部使用:

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




if($('body').scrollTop() + $('body').height() > getheight() -100 ) {
//alert near bottom
}
});

许多其他解决方案对我不起作用,因为在滚动到底部时,我的div触发了2次警报,当向上移动时,它也触发了几个像素,所以解决方案是:

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


alert('reached bottom!');
}
});

我用这个测试来检测滚动到达底部: event.target.scrollTop === event.target.scrollHeight - event.target.offsetHeight

Safari可以滚动到导致应用程序bug的页面底部。使用>=而不是===解决此问题。

container.scrollTop >= container.scrollHeight - container.clientHeight

如果有人想要一个普通的JavaScript解决方案,并且需要检测用户何时滚动到<div>的底部,我设法通过使用这些代码行来实现它

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 });

以下是最简单的方法:

const handleScroll = () => {
if (window.innerHeight + window.pageYOffset >= document.body.offsetHeight) {
console.log('scrolled to the bottom')
}}


window.addEventListener('scroll', handleScroll)

(2021) 这里有很多答案涉及element的引用,但是如果你只关心整个页面,只需使用:

function isBottom() {
const { scrollHeight, scrollTop, clientHeight } = document.documentElement;
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
return distanceFromBottom < 20; // adjust the number 20 yourself
}

我用纯JS做了这个非常简单的方法。

function onScroll() {
if (window.pageYOffset + window.innerHeight >= document.documentElement.scrollHeight - 50) {
Console.log('Reached bottom')
}
}
window.addEventListener("scroll", onScroll);