Javascript: como detectar se a janela do navegador é rolada para baixo?

187

Preciso detectar se um usuário está rolado até o final de uma página. Se eles estiverem na parte inferior da página, quando eu adicionar novo conteúdo à parte inferior, rolarei automaticamente para a nova parte inferior. Se eles não estiverem na parte inferior, eles estão lendo o conteúdo anterior mais alto na página, então eu não quero rolar automaticamente eles, pois eles querem ficar onde estão.

Como posso detectar se um usuário está rolado para a parte inferior da página ou se ele rolou mais alto na página?

Andrew
fonte
1
Este é trabalhado em Angular 6 -> stackoverflow.com/a/42547136/621951
Günay Gültekin 11/11

Respostas:

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

Ver demonstração

mVChr
fonte
29
Não funciona quando os elementos html / corpo estão definidos para 100% (de modo que o corpo preenche toda a altura do visor)
Grodriguez
5
Use em document.documentElement.scrollTopvez de window.scrollYpara o IE. Não tenho certeza de quais versões, se houver, do IE suportam window.scrollY.
Batandwa
3
Não funciona no Chromium versão 47.0.2526.73 Criada no Ubuntu 14.04, executando no SO elementar 0.3.2 (64 bits)
K - A toxicidade no SO está aumentando.
9
Usei document.body.scrollHeight em vez de offsetHeight (no meu caso, offsetHeight era sempre menor que a window.innerHeight)
Oliver
1
@KarlMorrison, você pode tentar a resposta premiada (por @Dekel) com o seu navegador?
Basj
115

Código atualizado para todos os principais navegadores de suporte (incluindo IE10 e IE11)

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

O problema com a resposta atualmente aceita é que window.scrollYnão está disponível no IE.

Aqui está uma citação de mdn sobre o scrollY:

Para compatibilidade entre navegadores, use window.pageYOffset em vez de window.scrollY.

E um trecho de trabalho:

Nota para mac

Com base no comentário de @ Raphaël, houve um problema no mac devido a um pequeno deslocamento.
A seguinte condição atualizada funciona:

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

Não tive a chance de testá-lo mais, se alguém puder comentar sobre esse problema específico, será ótimo.

Dekel
fonte
Trabalho confirmado no FF, Chrome, IE10, Chrome para Android. Obrigado @Dekel!
Basj
2
Por estranho que pareça, apenas no meu navegador tenho 1 px e, portanto, a condição não é acionada. Não sei por que, tive que adicionar alguns px extras para fazê-lo funcionar.
Sharjeel Ahmed
3
em computadores Mac, a condição abaixo não é atendida por causa de um pequeno deslocamento (~ 1px), atualizamos a condição da seguinte maneira:(window.innerHeight + window.pageYOffset) >= document.body.offsetHeight - 2
Raphaël
4
thx @Dekel! na verdade, descobrimos que window.pageYOffset é um flutuador no mac. Nossa solução final é (window.innerHeight + Math.ceil(window.pageYOffset + 1)) >= document.body.offsetHeight.
Raphaël
2
Não funciona nos casos em que o corpo possui um estilo que define a altura para 100%
raRaRa
56

A resposta aceita não funcionou para mim. Isso fez:

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

Se você deseja oferecer suporte a navegadores mais antigos (IE9), use o alias window.pageYOffsetque possui um suporte um pouco melhor.

Ryan Knell
fonte
1
não funciona no IE10 / 11. Verifique a resposta de Dekel ( stackoverflow.com/questions/9439725/… ) para obter suporte ao IE. Trabalhou para mim #
Herr_Schwabullek
As outras respostas acionavam o console.log () toda vez que eu rolava, não apenas quando estava na parte inferior da página. Esta resposta funcionou para mim no Chrome.
Defcronyke
Se você se livrar do window.scrollY, que não funciona em ie ou edge, esta é uma resposta decente. Substitua por: (window.innerHeight + window.pageYOffset)> = document.body.scrollHeight
colemerrick
21

Eu estava procurando uma resposta, mas não encontrei uma exata. Aqui está uma solução javascript pura que funciona com o Firefox, IE e Chrome mais recentes no momento desta resposta:

// 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
fonte
4
Isso quase funcionou para mim, mas eu tinha que usar ((document.documentElement && document.documentElement.scrollHeight) || document.body.scrollHeight)em vez de apenas document.body.scrollHeightpara a conta para os casos em html / corpo estão definidos para height: 100%
Grodriguez
1
@Grodriguez Obrigado pela informação! Pode ser útil para nós no futuro! :-)
pasztorpisti 23/10
15

Isso funciona

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

Se você deseja oferecer suporte a navegadores mais antigos (IE9), substitua window.scrollY por window.pageYOffset

Ifeanyi Amadi
fonte
1
este trabalho reage em 2019. trabalha com corpo a 100% de altura, vale a pena com html 100% de altura. trabalhe com chrome, safari, firefox, edge.
angry kiwi
Apenas uma observação: a nomeação deve ser alterada - as variáveis ​​devem ser alteradas. Como scrollHeight mostra a altura total da página e totalHeight mostra o ponto de rolagem atual, é um pouco confuso.
Vladimir Marton
4

Eu apenas comecei a olhar para isso e as respostas aqui me ajudaram, então obrigado por isso. Expandi um pouco para que o código esteja seguro desde o IE7:

Espero que isso seja útil para alguém.

Aqui, tem um violino;)

    <!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
fonte
Tipo de obras. Mas não é muito preciso. Ele considera que ele é rolado para a parte inferior desde que você esteja a cerca de 16px da parte inferior.
Peter Hall
4

Se você estiver configurando height: 100%algum contêiner <div id="wrapper">, o seguinte código funcionará (testado no Chrome):

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

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

Esta resposta irá corrigir casos extremos, porque pageYOffseté doubleenquanto innerHeighte offsetHeightsãolong , portanto, quando o navegador fornece as informações, você pode ter um pixel curto. Por exemplo: na parte inferior da página, temos

verdade window.innerHeight = 10.2

verdade window.pageYOffset = 5.4

verdade document.body.offsetHeight = 15.6

Nosso cálculo passa a ser: 10 + 5,4> = 16, o que é falso

Para consertar isso, podemos fazer Math.ceilo pageYOffsetvalor.

Espero que ajude.

itay yahalom
fonte
3

se você ama jquery

$(window).scroll(function() {
  if($(window).scrollTop() + $(window).height() >= $(document).height()) {
    // doSomethingHere();
  }
});
Eka putra
fonte
E quem não ama jQuery ...
Josh Habdas
2
@JoshHabdas browsers
Toni Michel Caubet
2

Você pode ver o infinito pergaminho do jquery:

http://www.infinite-scroll.com/infinite-scroll-jquery-plugin/

Parece que ele faz o que você está pedindo, supondo que você esteja disposto a usar a biblioteca jquery e não esperando um método JS puro e estrito.

Kai Qing
fonte
2
Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada.
Bobthedeveloper 20/05
@Hatsjoem Ele está vinculando a um plugin. Quais são exatamente as "partes essenciais" que devem ser copiadas? Quem se importa se a resposta "se tornar inválida se a página vinculada mudar"? Se o link for quebrado, significa que o plug-in foi descontinuado e não existe mais - mesmo se você adicionar mais informações à resposta, ele ainda será inválido. Caramba, as respostas somente de links não são necessariamente ruins.
Dcastro 20/05
@Hatsjoem Além disso, de meta : "Quando a biblioteca referenciada está em um local conhecido e estável, esse tipo de resposta geralmente é ruim, mas ainda assim : diz" use this ".
Dcastro 20/05
Além disso, o Google provavelmente ainda existirá se a rolagem infinita alterar esse URL. O objetivo é usar esse plug-in, portanto, se o link acabar, basta pesquisar no Google jquery rolagem infinita. Você provavelmente encontrará o que precisa.
Kai Qing
2

Surpreendentemente, nenhuma das soluções funcionou para mim. Eu acho que é porque eu cssestava bagunçado e bodynão envolvia todo o conteúdo ao usá-lo height: 100%(ainda não sei por que). No entanto, ao procurar uma solução, encontrei algo bem ... basicamente o mesmo, mas talvez valha a pena olhar - sou iniciante em programação, desculpe se está fazendo o mesmo mais devagar, tem menos suporte ou algo do tipo aquele...

window.onscroll = function(evt) {
  var check = (Element.getBoundingClientRect().bottom - window.innerHeight <= 0) ? true : false;
  if (check) { console.log("You're at the bottom!"); }
};
Coldark
fonte
2
$(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");
    }

}
Zihan Zhang
fonte
idk uma perspectiva diferente. Mas a resposta aceita é melhor, com certeza
Zihan Zhang
2
const handleScroll = () => {
    if (Math.round(window.scrollY + window.innerHeight) >= Math.round(document.body.scrollHeight)) {
        onScroll();
    }
};

Este código funcionou para mim no Firefox e IE também.

Arokia Prabha
fonte
1

Usando defaultViewe documentElementcom o snippet de código funcional incorporado:

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>

Josh Habdas
fonte
1

Você pode verificar se o resultado combinado da altura da janela e da parte superior da rolagem é maior que o do corpo

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

Oussama Essamadi
fonte
0

Eu tive que criar uma maneira (em Java) de rolar sistematicamente para baixo, procurando por um componente para o qual eu não conhecia o XPath correto (longa história, então apenas continue). Como acabei de afirmar, eu precisava rolar para baixo enquanto procurava por um componente e parar quando o componente foi encontrado ou na parte inferior da página.

O seguinte trecho de código controla a rolagem para baixo na parte inferior da página:

JavascriptExecutor js = (JavascriptExecutor) driver;
boolean found = false;
long currOffset = 0;
long oldOffset = 0;
do
{
    oldOffset = currOffset;
    // LOOP to seek the component using several xpath regexes removed
    js.executeScript("window.scrollBy(0, 100)");
    currOffset = (Long)js.executeScript("var offset = window.window.pageYOffset; return offset;");
} while (!found && (currOffset != oldOffset));

A propósito, a janela é maximizada antes que esse trecho de código seja executado.

hfontanez
fonte
0

A resposta aceita não funcionou para mim. Isso fez:

const element = document.createElement('div');
document.body.appendChild(element);
document.addEventListener('scroll', () => {
    const viewportHeight = window.innerHeight;
    const distance = element.getBoundingClientRect().top;
    if (Math.floor(distance) <= viewportHeight) {
        console.log('yep')
    } else {
        console.log('nope')
    }
})
mqliutie
fonte
0

Encontrei duas soluções que funcionaram para mim:

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

E o outro:

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