Welcome to a tutorial on how to create an infinite page scroll with vanilla Javascript. If you have been following up with social media – Facebook, Twitter, Instagram, etc… Then you should not be a stranger to that “scroll down to load more contents” interface. Yep, that is exactly what we will walk through in this guide – An example of infinite scroll using only pure Javascript. Read on!
ⓘ I have included a zip file with all the example source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.
TABLE OF CONTENTS
DOWNLOAD & NOTES
Firstly, here is the download link to the example code as promised.
QUICK NOTES
- If not using PHP, change
endless.url
in2-iscroll.js section A
to your own server-side script. - Launch
1-iscroll.html
in the browser. Captain Obvious – Usehttp://
notfile://
.
EXAMPLE CODE DOWNLOAD
Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
JAVASCRIPT INFINITE SCROLL
All right, let us now get into the steps of creating a simple endless scroll with Javascript.
STEP 1) CONTENT PAGE
<!-- (A) CONTENTS WRAPPER -->
<div id="page-content"></div>
<!-- (B) JUST SOME COSMETICS FOR DEMO -->
<style>
#page-content { background: lightblue; }
.page-demo { height: 1600px; }
</style>
That’s all, as straightforward as can be. We only need a <div id="page-content">
wrapper to load the contents into.
STEP 2) INFINITE SCROLL JAVASCRIPT
2A) FLAGS & SETTINGS
var endless = {
// (A) PROPERTIES & FLAGS
url : "3-dummy.php", // change this to your own!
first : true, // loading first page?
proceed : true, // ok to load more pages? "lock" to prevent loading multiple pages
page : 0, // current page
hasMore : true, // has more content to load?
// ...
}
All the infinite scroll mechanics are contained within the var endless
object. Right at the top, we have a bunch of “control flags”… Will explain why these are useful below.
2B) INITIALIZE INFINITE SCROLL
// (B) INITIALIZE INFINITE SCROLL
init : () => {
// (B1) LISTEN TO END OF PAGE SCROLL - LOAD MORE CONTENTS
window.addEventListener("scroll", () => {
if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) { endless.load(); }
});
// (B2) LOAD INITIAL PAGE
endless.load();
}
window.addEventListener("DOMContentLoaded", endless.init);
init()
loads on DOM content ready, and initializes the endless scroll.
- (B1) Attach a page scroll listener to the window, run
endless.load()
when the hits the bottom of the page. - (B2) Run
endless.load()
itself to load the first page from the server.
2C) AJAX LOAD CONTENT
// (C) AJAX LOAD CONTENT
load : () => { if (endless.proceed && endless.hasMore) {
// (C1) ENSURE ONLY 1 PAGE CAN LOAD AT ONCE
endless.proceed = false;
// (C2) PAGINATION & POST DATA
var data = new FormData(),
nextPg = endless.page + 1;
data.append("page", nextPg);
// data.append("KEY", "VALUE");
// (C3) AJAX FETCH CONTENT
fetch(endless.url, { method:"POST", body:data })
.then(res => res.text())
.then(res => {
// (C3A) NO MORE CONTENT
if (res == "END") { endless.hasMore = false; }
// (C3B) APPEND CONTENT INTO HTML WRAPPER
else {
var el = document.createElement("div");
el.innerHTML = res;
document.getElementById("page-content").appendChild(el);
endless.proceed = true; // unlock
endless.page = nextPg; // update current page
// (C3C) FIRST PAGE ONLY - MAKE SURE CONTENT COVERS WINDOW HEIGHT
if (endless.first) {
if (document.body.scrollHeight <= window.innerHeight) { endless.load(); }
else { endless.first = false; }
} else { endless.first = false; }
}
});
}}
Dumb trolls should be thinking “just fetch the contents, this is so complicated and stupid”. Feel free to do it your way, learn the hard way. All of the below have been contributed by people over time – You will run into the same problems, and implement all of these in one way or another.
endless.proceed
flag.- (C) Proceed with loading only when the flag is true –
load : () => { if (endless.proceed && endless.hasMore)
. - (C1) “Lock” the function once it starts –
endless.proceed = false
. - (C3B) “Unlock” after the current fetch has ended –
endless.proceed = true
.
- To keep track of the number of pages loaded, we introduce
endless.page
andendless.hasMore
. - (C2) Calculate next page to load
nextPg = endless.page + 1
, send it to server –data.append("page", nextPg)
. - (C3B) Update the current page on load –
endless.page = nextPg
. - (C3A) The server should respond with
END
when there is no more content to serve – We setendless.hasMore = false
to preventload()
from firing.
- (C3C) Basically, we detect the height of the content on the first loading cycle
endless.first
. Load until the content reaches the bottom of page.
STEP 3) SERVER-SIDE CONTENT
<?php
// (A) NO MORE CONTENT TO SERVE
if ($_POST["page"]==5) { echo "END"; }
// (B) SERVE DUMMY PAGE
else { echo "<div class='page-demo'>PAGE ".$_POST["page"]."</div>"; } ?>
Lastly, this is just a dummy server-side script – Output whatever content you are working on, with whatever language you are using. Things to take note of:
- The Javascript will POST a
page
over, use this to do pagination as required. - Output
END
if there is nothing left to show.
EXTRA BITS & LINKS
That’s the end of the tutorial, and here are a few extras that you may find useful.
COMPATIBILITY CHECKS
- Arrow Functions – CanIUse
- Fetch API – CanIUse
Should not run into any compatibility issues with all modern browsers.
NOTE – BAD FOR SEO
Also, a piece of bad news for you SEO lovers. Even though some search engines are smart enough to understand AJAX calls, they may not “scroll down” to load more content; Infinite scrolling is only good for certain types of content, and please do not use it to “hide” your useful content… For example, “scroll down to read more” for an article. You will end up on the bad side of SEO practice.
TUTORIAL VIDEO
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you to build a better project, and if you have anything to add to this guide, please feel free to comment below. Good luck and happy coding!
Any idea to get document.getElementById after the ajax load ?
We are unable to find id after ajax load …
Sorry, I don’t quite catch your question. The above example is already doing
document.getElementById("page-content").appendChild(el)
on AJAX load.If you are getting “cannot find element” errors, that is probably because you have assigned the wrong ID.
Thank you !
Your script is working very well.
You can check the result on : LINK REMOVED => https://code-boxx.com/faq/#nolink
I have made some modification to your scripts for my needs.
1. Use the entire url because if you have your scripts on several pages with SEO directives like dash in the url it can generate a directory error.
xhr.open(‘POST’, “https://www.completeurl.com/ajax-page.php”);
2. I don’t know why but on full hd screens it is unable to detect that the user is at the bottom of the page completely. I just put -4000 for sure we load but you can try with – 500
if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight – 4000) { endless.load(); }
3. I post the width of the visitor’s screen in the post that allows me to push div the correction according to the width.
width = window.screen.width;
data.append(‘width’, width);
Great Script thx for your help 🙂
Hi!,
First of all, I love you site! Straight, clear and usable for beginners and advanced codes alike!
I was wondering, would it be possible to ‘semi-scroll’ through e.g. previousPage/currentPage/nextPage and shift/replace them depending on which way the user scrolls? That way you might be able to achieve true infinite scrolling (depending on content of course 😉 ). I’m not an ES-professional but in theory it sounds feasable…
That is called “lazy pagination” then. Load the next page when user hits the bottom, load last page if hits the top. Problem is, what if the page content does not fill up the entire height of the screen?