jQuery Photo Slide Show with Slick Caption Tutorial Revisited

Written by Kevin Liew on 16 Dec 2009
266,278 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
coolboykl 15 years ago
Hi Kevin

Thanks for such a cool script, I have successfully integrate with our website at http://secq.me . Do have a check when u free.. (Click the little lady icon to start the slideshow..)

One quick question, what is the best approach that allows our user to start and stop the slide show at will?
Currently I start the slideshow() function in $(document).ready function, I also hide the slideshow DIV, when our user click the icon, it will toggle (hide or show) on the slideshow DIV, however this is not desirable result, as slideshow has started, this may not pointing to the first slide when user show the DIV.

I have try to call slideshow() function when user click the icon.. but this is in a way starting multiple instance of slideshow(), correct? which may screw up the whole slideshow..

Any advice..

Thanks
James
Reply
Kevin Liew Admin 15 years ago
You need to create two buttons. And then, refer to line 31, you can see it has a hovering event to stop and activate the slideshow. You can do the same but attach them to click event of your buttons.

$(#stop').click(
function () {
clearInterval(timer);
});

$(#play').click(
function () {
timer = setInterval('gallery()',speed);
});
Reply
coolboykl 15 years ago
Thanks! appreciated!
Reply
Robin 15 years ago
Fantastic, thank you! NB there are opening quotes missing on the button IDs in this code - it should be $('#stop').click and $('#play').click, so fix this if you copy & paste this code!
Reply
Dominic 15 years ago
Hi, Have you figured out how to stop/start the slideshow yet? I would be very interested to know.
Reply
filip 15 years ago
Hi,
Thanks for the script and the tutorial!
I'd like to add two buttons, for moving to next and previous image, but just can't figure out how to do it... Thanks in advance.
Reply
Phil 15 years ago
I'd like to do the same. I don't have much experience with JQ
Reply
Kevin Liew Admin 15 years ago
Hi guys, sorry, but this slider wouldn't able to do that. It will require some intense modification :/
Reply
Armysniper89 15 years ago
If I had six slides, is there a way I could show like circles or squares to show which slide is currently active out of the six so the user could click on the button and go to that specific slide (or at the very least, a next previous slide button?)
Reply
Yen 15 years ago
i love this slideshow, but how can i put multiple slideshow in one page? i wanted to put 4 of this slideshow as a header of my site..
Thank you so much..
:)

Reply
Lionard 15 years ago
Very good! It's possible add this in "wordpress" : there is a plugin or a guide to put it into wordpress (3.0.5 in my case).
Many Thnaks!
Reply
Kevin Liew Admin 15 years ago
Hi Lionard, pretty sure it's possible, but I can't guide you.
Reply
Tyler Schuett 15 years ago
It's extremely possible. I use it all the time in fact. You just need to make sure that you place your script call tags in the right order. If you need help let me know and I will be more than happy to.
Reply
Frank 15 years ago
Hey,

I have only a problem with ie8, the slide show is speeding up? Chrome and FF works fine..

Did i something wrong?
Reply
Davide 15 years ago
I have found the same problem with validation for:
document type does not allow element "li" here
…id="slideshow-caption" class="caption"><div class="slideshow-caption-container….

I assume if I have all the code that in its entirety then it is javascript generated content
How is this fixed?
Reply
Kevin Liew Admin 15 years ago
You need to wrap the javascript with <![[CDATA tag... it's the error generated from the html code inside the javascript.
Reply
Davide 15 years ago
I also have the validation error when checking the code by entering the url on w3c website
document type does no t allow element "li" here
…id="slideshow-caption" class="caption"><div class="slideshow-caption-container…

I have the code fully expanded so assume this is a javascript generated error and wondered how I hide it
Reply
Kevin Liew Admin 15 years ago
continued form the comment below. w3c validator parsed the html tags in the javascript section. So, you need the <![[CDATA tag to wrap around the javascript so that the parser will skip that section.
Reply
Nicolas 15 years ago
Hi,
I use images with tranparent background, so they are surrounded by a black border. I don 't know what causes this and how to remove it. Do you?

Thanks.
Reply
Kevin Liew Admin 15 years ago
not so sure, there is not border declared in the CSS. Could it be your CSS code?
Reply
Arnout 15 years ago
Hi!

This is really nice! Tnx for sharing. I have a question. Is it possible to fade the text from left to right in stead of up and down?

Thanks in advance!

Arnout
Reply
Kevin Liew Admin 15 years ago
possible, it needs fair a bit of modification thou... can be quite a hassle.
Reply
Chris 15 years ago
How do you copy and paste this to a html page I have this to work now embedding this

Thanks
Reply
Jerry Lee 15 years ago
Man, I don't know why I struggle with jquery, but this one worked like a charm. Thanks!
Reply
Viktor 15 years ago
Cool! This Version VALID and support UMI-CMS with XSLT
Reply
Kevin Liew Admin 15 years ago
that's the whole point of this revisit :)
Reply