jQuery Photo Slide Show with Slick Caption Tutorial Revisited

Written by Kevin Liew on 16 Dec 2009
224,150 Views • Tutorials

Introduction

If you have been reading my website from the start you would have read this tutorial:

Simple jQuery Image Slide Show with Semi Transparent Caption

It's a very famous post because it has been showcased in several major web design blogs so many times and I received a lot of traffic from it. Thanks guys. I get a lot of comment and as I replied to those comments and do some quick fixes, I realized that this script has a caption bug and inefficient and not up to standard (oh well, that's the time when I was start picking up jQuery :)), so I have decided to do revisit to solve all those problems discovered by readers. I rewrote the html structure and modify the script.

Mission Objectives:

  • Restructure the HTML, more semantic
  • Fix the caption bug, it displays the next caption too fast
  • W3C standard compliant, using appropriate attribute to store title and description
  • Cross Browser - Chrome, Safari, IE6, 7, 8 and Firefox.

However, one thing though, it needs javascript, if your browser is javascript disabled, sorry, there is no graceful degradation for this script, it will just display the first item.

Advertisement

1. HTML

Yes, I'm using list this time :) This is how it should have been afterall. No more REL attribute, we wil be using TITLE Attribute to store the heading and ALT attribute to store the description. For the caption elements, it will be added using jQuery. So, this is it - a clean and simple HTML code.

<ul class="slideshow">
	<li class="show"><a href="#"><img data-src="images/s1.gif" width="450" height="200" title="Slide 1" alt="Short Description"/></a></li>
	<li><a href="#"><img data-src="images/s2.gif" width="450" height="200" title="Slide 2" alt="Short Description"/></a></li>
	<li><a href="#"><img data-src="images/s3.gif" width="450" height="200" title="Slide 3" alt="Short Description"/></a></li>
</ul>

2. CSS

CSS code is rewritten completely. I guarantee it's cross browser compliant. They all look identical and it works great :) I did learn a lot of CSS technique through this blog. We all can improve our skills through tips, tricks, trials and errors. Read these posts to learn more about CSS:

body {
	font-family:arial;	
	font-size:12px;
}

ul.slideshow {
	list-style:none;
	width:450px;
	height:200px;
	overflow:hidden;
	position:relative;
	margin:0;
	padding:0;
	
}	

ul.slideshow li {
	position:absolute;
	left:0;
	right:0;
}

ul.slideshow li.show {
	z-index:500;	
}

ul img {
	border:none;	
}

#slideshow-caption {
	width:450px;
	height:70px;
	position:absolute;
	bottom:0;
	left:0;	
	color:#fff;
	background:#000;
	z-index:500;
}

#slideshow-caption .slideshow-caption-container {
	padding:5px 10px;	
	z-index:1000;	
}

#slideshow-caption h3 {
	margin:0;
	padding:0;	
	font-size:14px;
}

#slideshow-caption p {
	margin:5px 0 0 0;
	padding:0;
}

3. Javascript

We will going to use call back function to display caption. This will solve the "Caption Is Appearing Before The Next Slide Syndrome" :). Not too much of changes in javascript but I do added a feature though. On mouse over the slide will pause, and resume it back on mouse out. I think it's a good touch.

$(document).ready(function() {		
	
	//Execute the slideShow, set 4 seconds for each images
	slideShow(2000);

});

function slideShow(speed) {


	//append a LI item to the UL list for displaying caption
	$('ul.slideshow').append('
  •  
'); //Set the opacity of all images to 0 $('ul.slideshow li').css({opacity: 0.0}); //Get the first image and display it (set it to full opacity) $('ul.slideshow li:first').css({opacity: 1.0}).addClass('show'); //Get the caption of the first image from REL attribute and display it $('#slideshow-caption h3').html($('ul.slideshow li.show').find('img').attr('title')); $('#slideshow-caption p').html($('ul.slideshow li.show').find('img').attr('alt')); //Display the caption $('#slideshow-caption').css({opacity: 0.7, bottom:0}); //Call the gallery function to run the slideshow var timer = setInterval('gallery()',speed); //pause the slideshow on mouse over $('ul.slideshow').hover( function () { clearInterval(timer); }, function () { timer = setInterval('gallery()',speed); } ); } function gallery() { //if no IMGs have the show class, grab the first image var current = ($('ul.slideshow li.show')? $('ul.slideshow li.show') : $('#ul.slideshow li:first')); //trying to avoid speed issue if(current.queue('fx').length == 0) { //Get next image, if it reached the end of the slideshow, rotate it back to the first image var next = ((current.next().length) ? ((current.next().attr('id') == 'slideshow-caption')? $('ul.slideshow li:first') :current.next()) : $('ul.slideshow li:first')); //Get next image caption var title = next.find('img').attr('title'); var desc = next.find('img').attr('alt'); //Set the fade in effect for the next image, show class has higher z-index next.css({opacity: 0.0}).addClass('show').animate({opacity: 1.0}, 1000); //Hide the caption first, and then set and display the caption $('#slideshow-caption').slideToggle(300, function () { $('#slideshow-caption h3').html(title); $('#slideshow-caption p').html(desc); $('#slideshow-caption').slideToggle(500); }); //Hide the current image current.animate({opacity: 0.0}, 1000).removeClass('show'); } }

Updates

2010-09-10: Thanks to Rezzie who nailed the IE8 issue! :)

Updated the article and scripts, the link issue is fixed. :) Sorry for the delay.

Speed Issue

This is one of the issue that has been haunted me for a while, but thanks to Sam, one of our reader, he pointed out this would solve the issue, but with mixed result in IE.

Sam's solution, you need to add this:

$(window).focus(function () {
	timer = setInterval('gallery()', speed); 
});
$(window).blur(function () {
	clearInterval(timer);
});

James Burnett's solution, you modify the gallery function():

function gallery() {
	var current = ($('ul.slideshow li.show')? $('ul.slideshow li.show') : $('#ul.slideshow li:first'));

	if(current.queue('fx').length == 0) {
		
		// grab next image and animate code in here
		......
		......
		......
		
	}
}

Also, did some research, found the reason why it's doing it: From jQuery Animate Documentation: Because of the nature of requestAnimationFrame(), you should never queue animations using a setInterval or setTimeout loop. In order to preserve CPU resources, browsers that support requestAnimationFrame will not update animations when the window/tab is not displayed. If you continue to queue animations via setInterval or setTimeout while animation is paused, all of the queued animations will begin playing when the window/tab regains focus. To avoid this potential problem, use the callback of your last animation in the loop, or append a function to the elements .queue() to set the timeout to start the next animation.

Sorry guys, I don't have time to put all these together. Please let me know it works.

Randomize Slides

Simple yet effective solution from another reader - Blastos

Before the ending of function slideShow(), put this in:

//Generate a random number
var randNum = Math.floor(Math.random() * $('ul.slideshow li').length);

//Randomly pick up a slide
$('ul.slideshow li:eq('+randNum+')').addClass('show');

Caption doesn't appear for the first slide

I think it has to be the ommitted A tag for some users. Ammended the script, it should be fixed now.

Conclusion

I have made a lot of tutorials, and I think it's good to do a revisit to make it more efficient and solve some of the annoying bugs instead of quick fixes. So, yea, from now on, I will check my previous tutorials and rewrite them. :)

Like this tutorials? You can express your gratitude by visiting my sponsors on the sidebar, bookmark it and help me to spread this tutorial to our friends! :) Thanks!

Demo Download
Join the discussion

Comments will be moderated and rel="nofollow" will be added to all links. You can wrap your coding with [code][/code] to make use of built-in syntax highlighter.

488 comments
Nick Gowdy 12 years ago
How would I add thumbnails, that if clicked will change the image. Then continue looping through the images until it reaches the last image and then starting from the first image again?
Reply
Kevin Liew Admin 12 years ago
You can't do it in this tutorial, but you can use this plugin: http://www.pixedelic.com/plugins/diapo/
Reply
James Burnett 12 years ago
I fixed the speed issue by checking to see if the queue was empty before adding any more animations in the gallery function. It seems to work in Chrome and FireFox, but I haven't tried it in IE yet.


function gallery() {
var current = ($('ul.slideshow li.show')? $('ul.slideshow li.show') : $('#ul.slideshow li:first'));

if(current.queue('fx').length == 0) {
// grab next image and animate code in here
}
}
Reply
Kevin Liew Admin 12 years ago
Thanks James. I posted your solution as well in the tutorial.
Reply
Dustin Green 12 years ago
Can I use the programming part of this tutorial in a website I am re-designing?
Reply
Kevin Liew Admin 12 years ago
Yes, you can do whatever you want :)
Reply
octoos 12 years ago
well, great job.. implemented in cakephp, it work ! thanks
Reply
Tim 12 years ago
Is it possible to make the captions display right to left or left to right instead of top to bottom or bottom to top?
Reply
Steven 12 years ago
Hi, Ilove this tutorial and it was perfect for my job description. Thanks. I am getting a Javascript error in IE9 though. Do you know how i could fix this. See below for error. Thanks.

Line: 49
Character: 5
Code: 0
Error Message: Unable to get value of the property 'length': object is null or undefined
URL: http://localhost:55731/js/gallery.js

This is the code where the error is:

//trying to avoid speed issue
if(current.queue('fx').length == 0) {

.....

Reply
Stacey 12 years ago
This error is happening because the variable "fx" doesn't exist. To fix, change line 49 to read:

if(current.queue('current').length == 0) {
Reply
Stacey 12 years ago
Disregard previous comment. I am wrong. Keep the called variable as "fx." I modified the document ready function to read as follows:

$(document).ready(function() {

//Execute the slideShow, set 8 seconds for each image
slideShow(8000);
jQuery.fx.interval = 8000;

});

My browsers haven't detected any errors with the code so I'm assuming it's good to go.
Reply
Leesa Ward 12 years ago
Fantastic script, easy to modify the CSS to suit my needs, made creating a captioned slider a breeze. Thanks!
Reply
amber 12 years ago
Is there a way to turn off the caption and title on slides without them so it doesn't appear at all?
Reply
Simon 12 years ago
Hi
I can't make the randomise bit work (doh) - can you post some example code.
thanks for this slideshow its great!
Reply
nfrost21 12 years ago
I´m thinking about using this technique for a site i´m working on. Am a bit concerned that it may have a negative impact on SEO. Any ideas?
Reply
Page1Rocket 12 years ago
So long as the images are optimized and you use semantic headers it shouldn't affect SEO. To Google it'll simply look like an unordered list and so long as you use proper header tags for each slide then it'll make complete sense to search engines. I use a single image sprite for the slide images to improve page load time (SEO best practice).
Reply
Paul 12 years ago
Hi, Great tutorial, is their a way to make the images crossfade?

Cheers!
Reply
Ryan 12 years ago
By implementing the code on my page, the slideshow displays the first image but then doesnt start. I've included all the js files and the css and havent changed a thing. :(
Reply
Kevin Liew Admin 12 years ago
Try to download the demo, and start it from there.
Reply
bitra 11 years ago
Been experiencing the same problem. I solved it by including jQuery on my page.
Reply
Frank 12 years ago
I used the code for a project im doing but image doesnt change to next image
Reply