Tutorial Details
- Difficulty: Beginner - Intermediate
- Estimated Completion Time: 1 Hour
When working my way through a web gallery, I find it annoying when I must change pages; so in today’s tutorial, we will learn how to create an auto-generating, one-page, infinite scrolling gallery with PHP and AJAX. Let’s get started!
Step 1: Project Outline
We’ll begin with a normal gallery page that has a container for our images, and we’ll monitor the scroll position by calling a JavaScript function at a quick interval. Each time the scroll bar is near the bottom, we’ll make an AJAX request to an external PHP file, which returns a list of image names. Now, all we’ll need to do is add these images to our container, thus modifying the page height moving the scroll position higher.

Step 2: HTML Markup
We’ll work with a very basic setup: a header and the container for our images. The thumbnails will be grouped in sets of three rows, each will contain a link, referencing the full size image. After each group, we will add some text showing the total number of displayed images, and a link to the top of the page.
<body> <div id="header">Web Gallery | Infinite Scroll</div> <div id="container"> <a href="img/Achievements.jpg"><img src="thumb/Achievements.jpg" /></a> <a href="img/Bw.jpg"><img src="thumb/Bw.jpg" /></a> <a href="img/Camera.jpg"><img src="thumb/Camera.jpg" /></a> <a href="img/Cat-Dog.jpg"><img src="thumb/Cat-Dog.jpg" /></a> <a href="img/CREATIV.jpg"><img src="thumb/CREATIV.jpg" /></a> <a href="img/creativ2.jpg"><img src="thumb/creativ2.jpg" /></a> <a href="img/Earth.jpg"><img src="thumb/Earth.jpg" /></a> <a href="img/Endless.jpg"><img src="thumb/Endless.jpg" /></a> <a href="img/EndlesSlights.jpg"><img src="thumb/EndlesSlights.jpg" /></a> <p>9 Images Displayed | <a href="#header">top</a></p> <hr /> </div> </body>

Step 3: CSS
The CSS is also quite basic. First, we define the page colors and positioning for the header and paragraphs.
body{
background:#222;
color:#666;
}
#header{
font-family:Arial, Helvetica, sans-serif;
font-size:24px;
font-weight:bold;
text-align:left;
text-indent:35px;
margin: 0 auto;
width:800px;
margin-bottom:10px;
}
hr{
margin: 20px;
border:none;
border-top: 1px solid #111;
border-bottom: 1px solid #333;
}
p{
color:#444;
text-align:left;
font-size:10px;
margin-left: 20px;
margin-bottom: -10px;
}
a{
color:#444;
}

Step 4
Then, for the container and images, I used a bit of CSS3 to add round corners and shadows. Don’t forget "-moz-box-shadow" and "-moz-border-radius" for Firefox and "-webkit-box-shadow" and "-webkit-border-radius" for Chrome and Safari.

#container{
margin: 0 auto;
width:800px;
border:1px solid #333;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
font-family:Verdana, Geneva, sans-serif;
text-align:center;
}
img{
border:10px solid #444;
-moz-border-radius: 5px;
-webkit-border-radius: 10px;
margin: 15px;
}
img:hover{
border-color:#555;
-moz-box-shadow: 0px 0px 15px #111;
-webkit-box-shadow: 0px 0px 15px #111;
}
Step 5: PHP Script
This is going to be very short. We need to call the PHP script with the index of the next image we need as a parameter. First of all, we have to retrieve all the available image names from a directory and save them into an array. I organized my images in two folders: "thumb" and "img" which contain the thumbnails and actual images, respectively. Note that the thumbnails must have the exact same name as their corresponding full size images.

<?php
$dir = "thumb";
if(is_dir($dir)){
if($dd = opendir($dir)){
while (($f = readdir($dd)) !== false)
if($f != "." && $f != "..")
$files[] = $f;
closedir($dd);
}
We define a variable for the directory we want to get the image names from, test if it exists, and if we can open it, read all the file names from it. When reading an entire folder, we will always get two extra elements we may not want: "." – this stands for the current directory, and ".." – this stands for the parent directory. To compensate, we have to test if the element read is different from these two, then we can safely add it to our array.
$files[] = $f;
As a note, when adding an element to an array and not specifying the position to be placed in, it will always push the element to the end of the array.
Step 6
Now we have to build our response text. We are going to send back to the JavaScript a single string containing all the necessary file names separated by a semi-colon.
$n = $_GET["n"]; $response = "";
We get the URL parameter for the index of the next image we need, and we initialize our response text.
for($i = $n; $i<$n+9; $i++) $response = $response.$files[$i%count($files)].';'; echo $response; } ?>
As I said before, the images will be grouped in sets of three rows, each containing three images, so we only need nine images to return the file names for a group. We start at the index we got as parameter, $n, and go until $n+9. At each increment, we add our image name followed by ";" to the response text. Here is a little tricky part. We won’t have an infinite number of images; so in order to create the effect of an "infinite" gallery which never ends, each time the index of the next image is greater that the total number of images, we must start over from the beginning. This is done by applying the "modulo" or "%" function between the index and the total number of images.
$i%count($files)
As a result, we get the remainder of the division between these two elements. For example, if the index "$i" is "50" and the number of images "count($files)" is "45" the result will be "5". As well, if "$i" is "50" and "count($files)" is "65", the result will be "50". Finally, we have to send back our response text.
Step 7
Here is the complete PHP script. Just place your completed code within a new .php file.
<?php
$dir = "thumb";
if(is_dir($dir)){
if($dd = opendir($dir)){
while (($f = readdir($dd)) !== false)
if($f != "." && $f != "..")
$files[] = $f;
closedir($dd);
}
$n = $_GET["n"];
$response = "";
for($i = $n; $i<$n+9; $i++){
$response = $response.$files[$i%count($files)].';';
}
echo $response;
}
?>
Step 8: JavaScript
As usual, first we define some variables we will need later on.
var contentHeight = 800; var pageHeight = document.documentElement.clientHeight; var scrollPosition; var n = 10; var xmlhttp;

In order to determine weather the scroll bar is near the bottom of the page, we need three variables:
- "contentHeight" – the height of the initial gallery
- "pageHeight" – the height of the visible page in the browser
- "scrollPosition" – the position of the scroll bar measured from the top
Lastly, we need a variable for the next image index (which we are going to send to the PHP script), and a variable for the Ajax request object.
Step 9
We need to define a function that will add the images to our HTML container.
function putImages(){
if (xmlhttp.readyState==4){
if(xmlhttp.responseText){
A request object goes through different states as the request is made, each of which has a numerical value associated. The one we are interested in is the final state, when the request is complete and the value is "4". We first test if the request is in this state, and then check to see if we received a response.
Step 10
If both conditions are fulfilled, we have to tokenize the response text. This means we have to separate the file names into an array. Remember that in the PHP script we returned a single string with the names separated by semi-colons. Here is an example: Achievements.jpg;Bw.jpg;Camera.jpg;Cat-Dog.jpg;CREATIV.jpg;creativ2.jpg;Earth.jpg;Endless.jpg;EndlesSlights.jpg;
var resp = xmlhttp.responseText.replace("\r\n", "");
var files = resp.split(";");
There is a bit of a problem we have to deal with first; the response text may have at the beginning a new line character which we do not want. This is easily fixed with the "replace" function, that takes two parameters: "\r\n" – the new line character, and "" – empty string that will replace all occurrences of the first parameter. Now all we have to do is to split the string by our delimiter ";".
Step 11
Next, we have to add the images to our container.
var j = 0;
for(i=0; i<files.length; i++){
if(files[i] != ""){
document.getElementById("container").innerHTML += '<a href="img/'+files[i]+'"><img src="thumb/'+files[i]+'" /></a>';
j++;
if(j == 3 || j == 6)
document.getElementById("container").innerHTML += '';
else if(j == 9){
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed | <a href='#header'>top</a></p><hr />";
j = 0;
}
}
}
For every element in our array, we check if it isn’t an empty string, and add the thumbnail with the link on it. We have to keep a counter "j" in order to separate the images in rows. After every third and sixth thumbnail added, we create a new line, and after nine thumbnails added we put the text showing the total number of displayed images and a link to the top of the page.
Step 12
Here is the complete function.
function putImages(){
if (xmlhttp.readyState==4){
if(xmlhttp.responseText){
var resp = xmlhttp.responseText.replace("\r\n", "");
var files = resp.split(";");
var j = 0;
for(i=0; i<files.length; i++){
if(files[i] != ""){
document.getElementById("container").innerHTML += '<a href="img/'+files[i]+'"><img src="thumb/'+files[i]+'" /></a>';
j++;
if(j == 3 || j == 6)
document.getElementById("container").innerHTML += '';
else if(j == 9){
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed | <a href='#header'>top</a></p><hr />";
j = 0;
}
}
}
}
}
}
Step 13
Now we are going to define the function that will check if the scroll position is getting near the bottom, and makes the request to the server.
function scroll(){
if(navigator.appName == "Microsoft Internet Explorer")
scrollPosition = document.documentElement.scrollTop;
else
scrollPosition = window.pageYOffset;
First, we have to find the position of the scroll bar. Internet Explorer does this a bit differently, so we have to determine what browser the client is using, then just store the value in the variable we defined earlier.
Step 14
if((contentHeight - pageHeight - scrollPosition) < 500){

Now we check to see if we are about to reach the end of our gallery – if the part of the page visible in the browser is below the bottom 500px of the entire page. This isn’t an exact value, you may use a different one if you find it suitable. If this condition is true, we can continue on and add new images.
Step 15: Creating the XMLHttpRequest Object
We are ready to make the XMLHttpRequest object and send it. Again, for Internet Explorer the definition is a bit different, so we must compensate for this as well.
if(window.XMLHttpRequest)
//Firefox, Opera, Safari
xmlhttp = new XMLHttpRequest();
else
if(window.ActiveXObject)
//Internet Explorer
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
else
alert ("Bummer! Your browser does not support XMLHTTP!");
Step 16
Before sending the request, we have to specify the PHP script name on the server and insert the parameters we want to give it.
var url="getImages.php?n="+n;
This is a simple text variable representing the URL of the page.
Step 17
It’s time to send the request.
xmlhttp.open("GET",url,true);
xmlhttp.send();
The URL is set by calling the "open" method. The second parameter is the important one, this being the script’s URL. After doing so, all we need is to send it. This will run the PHP script and put in "xmlhttp.responseText" the return value of it.
Step 18
The final step is to place the new content on the page by calling the function we defined earlier "putImages" and to prepare our variables for the next request.

n += 9; contentHeight += 800; xmlhttp.onreadystatechange = putImages; } }
We have nine new images in the gallery, so we increment "n" with 9, and we need to change the page height; so increment "contentHeight" with 800.
Step 19
Here is the entire JavaScript we’ve used.
<script>
var contentHeight = 800;
var pageHeight = document.documentElement.clientHeight;
var scrollPosition;
var n = 10;
var xmlhttp;
function putImages(){
if (xmlhttp.readyState==4)
{
if(xmlhttp.responseText){
var resp = xmlhttp.responseText.replace("\r\n", "");
var files = resp.split(";");
var j = 0;
for(i=0; i<files.length; i++){
if(files[i] != ""){
document.getElementById("container").innerHTML += '<a href="img/'+files[i]+'"><img src="thumb/'+files[i]+'" /></a>';
j++;
if(j == 3 || j == 6)
document.getElementById("container").innerHTML += '';
else if(j == 9){
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed | <a href='#header'>top</a></p><hr />";
j = 0;
}
}
}
}
}
}
function scroll(){
if(navigator.appName == "Microsoft Internet Explorer")
scrollPosition = document.documentElement.scrollTop;
else
scrollPosition = window.pageYOffset;
if((contentHeight - pageHeight - scrollPosition) < 500){
if(window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else
if(window.ActiveXObject)
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
else
alert ("Bummer! Your browser does not support XMLHTTP!");
var url="getImages.php?n="+n;
xmlhttp.open("GET",url,true);
xmlhttp.send();
n += 9;
xmlhttp.onreadystatechange=putImages;
contentHeight += 800;
}
}
Step 20
The final thing that we must do is run the JavaScript at a specified interval.
<body onload="setInterval('scroll();', 250);">
Just set up the "onload" property of the "body" tag, and set its value to the "setInterval" function. This will run the "scroll" function every quarter of a second. Again, you may change this time value, but I found that it’s optimal for what we need.
Finished!
We are done! I hope you found this tutorial to be of help and useful. Please leave a message in the comment section below, should you need further assistance or advice.

Hey, looks cool. There is no demo or?
Please give a demo…
Really nice tutorial. Is there any demo? :)
a demo :-)
Nice! How to get the source code?
Nice tut, but demo would be nice
Bravo Alex!
A demo would be nice, indeed :)
Am I missing something or is there a not a demo to go with this tutorial?
I need to see a demo before I can follow this tutorial!
Nicely explained, useless without a demo.
How about a follow up that explains how to extract the images from say Flickr or Picassa — Picassa would be especially nice since I haven’t seen any tuts dealing with it.
Anyways, the tut is well done. Easy to follow. And off course a demo is what everyone expects nowadays but the pictures give a clear view of what the design will look like. If you want to see it in action, why not build it for yourself; after-all, that is what this here is all about.
If its sourcing from flickr I would want to make the scrolling disappear at the top of the window. Instead of having a very long page (i.e. remove the scroll bar altogether.
It would be great to see a demo. Am thinking this could be a behavior I have seen with SORTFOLIO.
A cool way to d stuff now.
JW please do a demo page.
This would be a really great tutorial except that it’s missing one vital part. Can you guess what that is?
Otimo artigo, mas coloca um demo pra gente analisar.
thanks
Where do you define the three columns? I don’t see it in the html or css, based on your code it looks like it’d all be horizontal. Oh, and it could use a demo :)
That is a great tutorial, as mentioned above, is there going to be a demo?
demo???? demo????
demo? lol.
There will not be a demo on nettuts since there is never a demo when PHP is used ( if i remember ). You could upload it to a server if you have one Alexandru and leave a link in a comment. :)
Most of the time the demo just links back to the creators server, if they have one.
Hi,
Demo is coming really soon!
Please add jQuery version that will be great for jQuery users ;) isn’t it?
Thankyou
This is a great idea. I may actually try this out on one of my current projects.
Lots of code jquery ore even php can do better, but iam impressed, deep “and if then that” thinking :)
With Kind Regards,
Hans
(The Netherlands)
Nice, I will be using this soon.
if no demo, then what about downloadable source code?
Sounds awesome but a demo would have been a great tool to actually see what’s all about. Gonna try to give it a shot anyway.
Very nice tut, thanks so much for posting it.
DEMO here: MFX.ro
Strange scroll…
Interesting effect. I’d be interested in the Flickr Dynamic Feed. That’d be great if it could grab them and insert them dynamically into the list items. I might have an idea about how to do it, but it’d involve the Flickr API, which I’m not a fan of. Great Tutorial, though! I really liked the simplicity of the PHP.
Very good nice looking gallery I have checked it with my localhost
Cool idea and execution but these kind of pages make my brain explode :) I rely on the scroll bar to let me know how long the full page is. This site keeps tricking you and you never know where the end is. I’m not sure if it is my ADD kicking in or the fact that I make my decision to scroll through a page or not by the scale of “can I view it in enough time before my boss thinks I am slacking”
On the other end, we all want people to stay on our sites longer. Maybe this is a good way to keep people on your site forever. I am sure there are some people determined to reach the end of the page no matter how long it takes. (they are probably still scrolling right now)
Great post !
It would be awesome if you added lightbox effects on these images !
Thanks
Really nice to see an example without the use of a library, easy to forget those libraries only do things already possible with pure js.
Waooo, excellent post and a really creative idea,
inspirational,
thanks for share.
that’s great tutorial tanks for sharing.
Nice one !
I agree with Steve Mullen, it feels a bit cold when I never get to the end of the page :)
It keeps going and going and going and going…
Pretty cool!
what a great gallery, which just dont want to end.
thanks for it
Just added jquery, its so smooth. You should have included that in the tut/
There are far more things to learn from this tutorial than the final demo/project!
Good tut! thanks.
Very cool Tut! Thx so much!
Yup! Demo up. Thanks Alexandru :)
I love it, The idea is great!
Bine ma, ce tare :) In sfarsit un web developer roman pe aici. Nu stiu daca mai sunt si altii pe Nettuts dar esti primul pe care-l vad. Keep it up.
:) Haha.. salut! cel putin stim ca suntem 2….
Trei ,,, si mai sunt destui … :) Sa creem “Liga romanilor de pe Nettuts” – si sa ne chinuim sa avem o luna numai de tutoriale scrise de romani :)
it demonstrates awesome use of ajax…
thanks for sharing this great technique…
took me a long time to realize there was a scroll bar on the right side of my browser as my screen nicely fit in the first nine images. Because of this, I did not have a clue that there was more to this page. Very easy for a user to overlook more content.
So, basically this is just another Lazy loader…
always wanted to know how to do this.
thanks for a great tutorial!
Excellent tut for the beginners.
Part two of this tutorial will be appreciated, Pagination and lightbox effect should be included.
CI version of this tutorial is most welcome.
Good use of PHP & Ajax. Thanks for sharing.
very well explained…. thank you…