Super simple jQuery slideshow with lazy loading

I recently had to create a page with 20+ slideshows. I was translating the page from a WordPress site. The original page builder had used the WordPress built in slideshow, which is easy, but did not do him any favors in terms of performance. The page loaded all the slideshows at once and when they got going, you could really feel the page bog down.

When I recreated the page I wanted to make sure this didn't happen. So my first idea was to not animate the slides; have them paused by default. But that wasn't enough, because even compressed, the page would be loading 8+ megabytes of images. I needed a way to progressively load the images as the user scrolled.

Now the site that I was building into already had enough JavaScript and it did not rank well in the Yahoo Speed Test or the Google Speed Test. So I didn't want to add any heavy plugins to the site. The slideshow also need to be easy to implement by the average person who does not know HTML all that well. I didn't want the user to have to add a bunch of classes to each image, or cumbersome markup. So it essentially works like this. There is a DIV with a class of "inlineSlideshow" that you drop your images into, and for the navigation, another DIV directly underneath with a class of "inlineSlideshowNav". That's it! Follow along and I'll show you how to set it up.

First we need the html

<div class="inlineSlideshow">
  <!-- Drop your images here -->
</div>
<div class="inlineSlideshowNav">
  <img class="backarrow" src="http://www.enjoysandiego.com/sdorg-images/presidential/arrow-backward.png" width="30" height="57" alt="Back"/>
  <img class="forarrow" src="http://www.enjoysandiego.com/sdorg-images/presidential/arrow-forward.png" width="30" height="57" alt="Forward"/>
</div>

That's all the HTML needed. Just drop your images into the inlineSlideshow DIV.

Now for the CSS.

.inlineSlideshow{width:100%;height:360px;position:relative;}
.inlineSlideshow img{position:absolute;display:none;}
.backarrow{left:43%;margin-right:10px;}
.forarrow{right:43%;margin-left:10px;}
.inlineSlideshowNav{margin:-70px 0 50px 0;z-index:100 !important;position:relative;text-align:center;}

Just a few lines. In order to get the images to stack on top of each other we need to set them to position:absolute. This takes them out of the page flow and will cause the containing DIV to collapse, so we must make sure the height on that is set. In this case, it's set to 360 pixels.

We also set the images to display:none. In the next step we will juse jQuery to show the first image at page load.

Now for the jQuery.

$('.inlineSlideshow').find('img:first-child').show();
	
$('.forarrow').click(function(){
			var lastImage = $(this).parent().prev().find('img:last-child');
			if(lastImage.is(":visible")!= true){
       
				 if($(this).parent().prev().find('.active').length == 0){//slideshow has not been initiated, no active class exists
var img = $(this).parent().prev().find('img:first-child'); img.next().addClass('active'); img.next().fadeIn(); }else{ var img = $(this).parent().prev().find('.active'); img.next().fadeIn(); img.next().addClass('active'); img.removeClass('active'); } } }); $('.backarrow').click(function(){ var secondImage = $(this).parent().prev().find('img:first-child').next(); if(secondImage.is(":visible")== true){ if($(this).parent().prev().find('.active').length == 0){//slideshow has not been initiated, no active class exists //do nothing }else{ var img = $(this).parent().prev().find('.active'); img.prev().addClass('active'); img.fadeOut('fast'); img.removeClass('active'); } } }); $(window).scroll(function(){ $('.inlineSlideshow').each(function(){ if(isScrolledIntoView(this)){ loadImages(this); } }); ; });

So a few things are happening here. Remember, the images are set to display:none by deault, so with the first line we are setting the first image to appear. Then we have two click functions for the forward arrow and backarrow, and finally a scroll function that fires whenever the user scrolls the page.

You might notice that inside the scroll function we are calling loadImages(). We'll add that function now.

function loadImages(slideshow){
	$(slideshow).children().each(function(){
		var dataSrc = $(this).data('src');
		$(this).attr('src',dataSrc);
		})
}

To make the lazy loading work, we add a data attribute called data-src to each image. Make sure to add the actual image link to this element, NOT the src attribute. On the src attribute you will use a very small loading image. You will do this for all the images. The jQuery will then take the data-src attribute and load the images when you scroll to the slideshow.

Simple, right? Leave me a comment if you have any questions!

Head on over to my GitHub page to grab the files.