JavaScript: Jak wykryć, czy okno przeglądarki jest przewijane do dołu?


187

Muszę wykryć, czy użytkownik jest przewijany na dół strony. Jeśli znajdują się na dole strony, gdy dodam nową treść na dole, automatycznie przewijam je do nowego dołu. Jeśli nie znajdują się na dole, czytają poprzednią treść wyżej na stronie, więc nie chcę ich automatycznie przewijać, ponieważ chcą pozostać tam, gdzie są.

Jak mogę wykryć, czy użytkownik jest przewinięty na dół strony lub czy przewinął wyżej na stronie?


1
Ten działa w Angular 6 -> stackoverflow.com/a/42547136/621951
Günay Gültekin

Odpowiedzi:


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

Zobacz demo


29
Nie działa, gdy elementy HTML / body są ustawione na 100% (tak, że body wypełnia całą wysokość rzutni)
Grodriguez

5
Użyj document.documentElement.scrollTopzamiast window.scrollYdla IE. Nie jestem pewien, które wersje IE obsługują window.scrollY.
Batandwa

3
Nie działa w wersji Chromium 47.0.2526.73 Zbudowany na Ubuntu 14.04, działający na podstawowym systemie operacyjnym 0.3.2 (64-bitowym)
K - Toksyczność w SO rośnie.

9
Użyłem document.body.scrollHeight zamiast offsetHeight (w moim przypadku offsetHeight był zawsze mniejszy niż okno.innerHeight)
Oliver

1
@KarlMorrison, czy możesz wypróbować nagrodzoną nagrodę (autorstwa @Dekel) w swojej przeglądarce?
Basj

115

Zaktualizowany kod do obsługi wszystkich głównych przeglądarek (w tym IE10 i IE11)

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

Problem z obecnie akceptowaną odpowiedzią polega na tym, że window.scrollYnie jest ona dostępna w IE.

Oto cytat z mdn dotyczący scrollY:

Aby zachować zgodność z różnymi przeglądarkami, użyj window.pageYOffset zamiast window.scrollY.

I działający fragment kodu:

Uwaga dla komputerów Mac

Na podstawie komentarza @ Raphaëla wystąpił problem w systemie Mac z powodu niewielkiego przesunięcia.
Działa następujący zaktualizowany warunek:

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

Nie miałem okazji go dalej testować, jeśli ktoś może skomentować ten konkretny problem, będzie świetnie.


Potwierdzono działanie na FF, Chrome, IE10, Chrome na Androida. Dziękuję @Dekel!
Basj

2
Dziwne, jak może to zabrzmieć, tylko w mojej przeglądarce brakuje mi 1 piksela, a zatem warunek się nie uruchamia. Nie jestem pewien, dlaczego, musiałem dodać kilka pikseli, żeby to działało.
Sharjeel Ahmed

3
na komputerach Mac warunek poniżej nie jest spełniony z powodu małego przesunięcia (~ 1px) zaktualizowaliśmy taki stan(window.innerHeight + window.pageYOffset) >= document.body.offsetHeight - 2
Raphaël

4
dzięki @Dekel! w rzeczywistości okazuje się, że window.pageYOffset jest zmiennoprzecinkowy na Macu. Nasze ostateczne rozwiązanie to (window.innerHeight + Math.ceil(window.pageYOffset + 1)) >= document.body.offsetHeight.
Raphaël

2
Nie działa w przypadkach, gdy ciało ma styl, który ustawia wysokość na 100%
raRaRa

56

Przyjęta odpowiedź nie działała dla mnie. To spowodowało:

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

Jeśli chcesz obsługiwać starsze przeglądarki (IE9), użyj aliasu, window.pageYOffsetktóry ma nieco lepszą obsługę.


1
nie działa w IE10 / 11. Sprawdź odpowiedź Dekela ( stackoverflow.com/questions/9439725/... ) pod kątem obsługi IE. Pracował dla mnie
Herr_Schwabullek

Inne odpowiedzi wyzwalały console.log () za każdym razem, gdy przewijałem, nie tylko kiedy znajdowałem się na dole strony. Ta odpowiedź działała dla mnie w Chrome.
Defcronyke

Jeśli pozbędziesz się window.scrollY, który nie działa w ie lub edge, jest to przyzwoita odpowiedź. Zamień na: (window.innerHeight + window.pageYOffset)> = document.body.scrollHeight
colemerrick

21

Szukałem odpowiedzi, ale nie znalazłem dokładnej. Oto czyste rozwiązanie javascript, które działa z najnowszymi przeglądarkami Firefox, IE i Chrome w momencie odpowiedzi:

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

4
To prawie działało dla mnie, ale musiałem użyć ((document.documentElement && document.documentElement.scrollHeight) || document.body.scrollHeight)zamiast po prostu document.body.scrollHeightuwzględnić przypadki, w których html / body są ustawione na wysokość: 100%
Grodriguez

1
@Grodriguez Dzięki za informację! Może się nam przydać w przyszłości! :-)
pasztorpisti

14

To działa

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

Jeśli szukasz wsparcia starszych przeglądarek (IE9) zastąpić window.scrollY z window.pageYOffset


1
ta praca z reakcją w 2019 roku. praca z ciałem 100% wzrostu, warta przy HTML 100% wysokości. praca z Chrome, Safari, Firefox, Edge.
zły kiwi

Tylko uwaga: nazewnictwo należy zmienić - zmienne należy zmienić. Ponieważ scrollHeight pokazuje całkowitą wysokość strony, a totalHeight pokazuje aktualny punkt przewijania, więc jest to trochę mylące.
Vladimir Marton

4

Właśnie zacząłem na to patrzeć, a odpowiedzi tutaj mi pomogły, więc dziękuję za to. Rozbudowałem się trochę, aby kod był bezpieczny aż do IE7:

Mam nadzieję, że okaże się to przydatne dla kogoś.

Masz skrzypce;)

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

Rodzaj prac. Ale to nie jest bardzo dokładne. Uważa, że ​​jest on przewijany w dół, o ile znajduje się w odległości około 16 pikseli od dołu.
Peter Hall

4

Jeśli korzystasz height: 100%z jakiegoś kontenera <div id="wrapper">, działa następujący kod (testowany w Chrome):

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

wrapper.onscroll = function (evt) {
  if (wrapper.scrollTop + window.innerHeight >= wrapper.scrollHeight) {
    console.log('reached bottom!');
  }
}

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

Ta odpowiedź naprawi przypadki na krawędzi, ponieważ pageYOffsetjest to doubleczas innerHeighti offsetHeightlong, więc kiedy przeglądarka podaje informacje, możesz mieć krótki piksel. Na przykład: u dołu strony mamy

prawdziwe window.innerHeight = 10.2

prawdziwe window.pageYOffset = 5.4

prawdziwe document.body.offsetHeight = 15.6

Nasze obliczenia stają się wtedy: 10 + 5,4> = 16, co jest fałszem

Aby to naprawić, możemy zrobić Math.ceilna pageYOffsetwartości.

Mam nadzieję, że to pomaga.


3

jeśli kochasz jquery

$(window).scroll(function() {
  if($(window).scrollTop() + $(window).height() >= $(document).height()) {
    // doSomethingHere();
  }
});

A kto nie lubi jQuery…
Josh Habdas

2
Przeglądarki @JoshHabdas
Toni Michel Caubet

2

Możesz zajrzeć do nieskończonego zwoju jquery:

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

Brzmi to tak, jakby robiło to, o co prosisz, zakładając, że chcesz korzystać z biblioteki jquery i nie licząc na czystą metodę JS.


2
Chociaż ten link może odpowiedzieć na pytanie, lepiej dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli zmieni się połączona strona.
bobthedeveloper

@Hatsjoem Linkuje do wtyczki. Jakie dokładnie „istotne części” należy skopiować? Kogo to obchodzi, jeśli odpowiedź „straci ważność, jeśli zmieni się linkowana strona”? Jeśli link zostanie zerwany, oznacza to, że wtyczka została wycofana i już nie istnieje - nawet jeśli dodasz więcej informacji do odpowiedzi, nadal będzie niepoprawna. Jezu, odpowiedzi tylko z linkiem niekoniecznie są złe.
dcastro

@Hatsjoem Również z meta : „Gdy wspomniana biblioteka znajduje się w dobrze znanej, stabilnej lokalizacji, tego rodzaju odpowiedź jest ogólnie słabą odpowiedzią, ale mimo to odpowiedź brzmi :„ użyj tego ”.
dcastro

Ponadto Google prawdopodobnie nadal będzie istniał, jeśli nieskończone przewijanie zmieni ten adres URL. Chodzi o to, aby użyć tej wtyczki, więc jeśli link umrze, wystarczy google search jquery nieskończonego przewijania. Prawdopodobnie znajdziesz to, czego potrzebujesz.
Kai Qing

2

Zaskakujące, że żadne z rozwiązań nie działało dla mnie. Myślę, że to dlatego, że mój csszostał zawalony i bodynie zawinął całej zawartości podczas używania height: 100%(jeszcze nie wiem dlaczego). Jednak szukając rozwiązania, wymyśliłem coś dobrze ... zasadniczo to samo, ale może warto przyjrzeć się - jestem nowy w programowaniu, więc przepraszam, jeśli działa tak samo wolniej, jest mniej obsługiwany lub coś w stylu że...

window.onscroll = function(evt) {
  var check = (Element.getBoundingClientRect().bottom - window.innerHeight <= 0) ? true : false;
  if (check) { console.log("You're at the bottom!"); }
};

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

}

mam inną perspektywę. Ale zaakceptowana odpowiedź jest na pewno lepsza
Zihan Zhang

2
const handleScroll = () => {
    if (Math.round(window.scrollY + window.innerHeight) >= Math.round(document.body.scrollHeight)) {
        onScroll();
    }
};

Ten kod działał również dla mnie w Firefox i IE.


1

Korzystanie z wbudowanego fragmentu kodu funkcjonalnego defaultViewi korzystanie documentElementz niego:

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>


1

Możesz sprawdzić, czy łączny wynik wysokości okna i góry przewijania jest większy niż ciała

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


0

Musiałem wymyślić sposób (w Javie), aby systematycznie przewijać w dół w poszukiwaniu komponentu, dla którego nie znałem prawidłowej XPath (długa historia, więc po prostu graj dalej). Jak właśnie powiedziałem, musiałem przewinąć w dół, szukając komponentu i zatrzymać się, gdy komponent zostanie znaleziony lub dojdzie do dołu strony.

Poniższy fragment kodu steruje przewijaniem w dół do dołu strony:

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

Nawiasem mówiąc, okno jest zmaksymalizowane przed wykonaniem tego fragmentu kodu.


0

Przyjęta odpowiedź nie działała dla mnie. To spowodowało:

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

0

Dwa rozwiązania, które okazały się dla mnie skuteczne:

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

I inni:

  window.addEventListener('scroll', function(e) {
    if (
      window.innerHeight + window.pageYOffset ===
      document.documentElement.offsetHeight
    ) {
      console.log('You are at the bottom')
    }
  })
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.