jQuery Photo Slide Show with Slick Caption Tutorial Revisited

Written by Kevin Liew on 16 Dec 2009
266,250 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
Chris 15 years ago
Love it!
Is there a way to slide the captions in from the left?
I can change the height/width to have my captions on the left but they slide up down. left rightwould be perfect too! Thanks
Reply
Kevin Liew Admin 15 years ago
sorry, you can do this in this tutorial.
Reply
Kevin Liew Admin 15 years ago
I meant... "you can't do this in this tutorial"
Reply
Anders 15 years ago
Hey. Nice tutorial. thanks.
I just have one question, Can I put more than one slideshow on a page, if so, how du I do it, because I dont seem to be able to figure it out.

Hope some one can help.
Agian thanks for the tutorial.
Reply
Julie 15 years ago
I also want to have multiple slideshows on the page, please advise how we achieve this. Thanks very much.
Reply
Adrián Pérez 15 years ago
Excellent Job you have done here with the slide show.... Is there a way to add "Forth" and "Back" functionallity to this code?....
Reply
Katie 15 years ago
Hi Adrian - I did that. I'll give you my code - email me at (myname) at yellowrubberball (dotdotdot) com
Reply
Adam 15 years ago
How would I make it stop after the last slide? I don't want it to start over from the beginning again bust instead just stay on the final slide.

Thanks!
Reply
Angie 15 years ago
Very nice. Is there an easy way to make it randomize the images?
Reply
Blastos 15 years ago
I second the request for randomizing. :)

I guess you'd have to read the whole UL to determine the number of LI, and then somehow address the LI's by number. Looks like 'next' is being used to advance through the LIs now?
Reply
Blastos 15 years ago
Okay. Got it figured out. Easier than I though. Make a random number, and then address a list item with li:eq(X) as seen here:

$('ul.slideshow li:eq('+randNum+')').addClass('show');

By the way, that line also fixes a bug if you don't start with a li that has class="show" (which you wouldn't if you are randomly starting). If that class isn't added to the one that you randomly start with, it will keep "popping up" between fades on the other list items, until the slide show gets around to the second display of the image when it applies
current.animate({opacity: 0.0}, 500).removeClass('show');
Reply
Kevin Liew Admin 15 years ago
Thanks Blastos! I've put your solution in this article.
Reply
Colt 15 years ago
I really need this for my website, I design my own website.. I know basic HTML... I need to know how to add this to my site.. I know how to upload files and paste codes into the documents and css.. could you help?
Reply
aditya 15 years ago
the speed of change of slide becomes high with time. i mean when u keep it open for 5-10 minutes the speed becomes high from seconds to less than 1 second.. can you reason it out and help...
Any solution please.
Reply
Vlad 15 years ago
I'm having the same problem with the speed increasing if I tab over to a different site.

Anyone find a solution?
Reply
Katie 15 years ago
Ditto. Is there a solution to this one yet?
Reply
Kevin Liew Admin 15 years ago
Hi All, sorry for not able to fix this immediately, it has been an issue I've been facing as well. I have just updated the article, please read the last section. I don't really have a solution at the moment, but what I've found hopefully will shed some light to you all. Let me know if you able to fix it. :)
Reply
John 15 years ago
this would be great if someone (a programmer) out there is able to solve this issue since this is a great slideshow script and this issue is kinda annoying. The semi solution does appear to help with Firefox, not tried it in IE yet.
Reply
Kevin Liew Admin 15 years ago
Good to hear that semi solution does work.
Reply
John 15 years ago
nope i was wrong it does not work, I thought it did slow thigns down but its still the same. :(
Reply
Davey 15 years ago
Hi guys here my solution....:

Primero desde luego - first of course:

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

y entonces en la función slideShow..- and then in slideShow function:

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

espero les sea de utilidad, chao...!! - I hope this will be useful.., bye!

djarmasmartinez@gmail.com



Reply
Darren 15 years ago
Thank you for this tutorial, it was just what I was looking for and easy enough for a beginner to do!
Oh it works perfectly in all of the latest browsers including IE9 :)
Reply
Pedro 15 years ago
Thanks for this tutorial, much appreciated. Im experiencing one slight problem however, hopefully you may have an idea on how to resolve it? When each new slide loads, there is a brief flash in the DIV underneath the gallery which shows the next slide text. YOu can see what i mean from the link below. Im quite new to web design so not really sure how this can be fixed. I had tried setting the z-index for the body div to a high value in the hope it would sit on top but this hasnt appeared to work. Any feedback is much appreciated.

http://www.gourmetwa.com.au/test/home.html
Reply
Kevin Liew Admin 15 years ago
In your text.css file, change the height of your gallery from 360 to 350px (that's the height of your image) and add overflow:hidden. That should nail it :)
Reply
Rick 15 years ago
Love this script - works as described. One question for you - is it possible to change the code to make the caption appear without moving up? In other words, a caption that doesn't animate up, but appears at the final position. Thank you.
Reply
Kevin Liew Admin 15 years ago
change this:

$('#slideshow-caption').slideToggle(300, function () {
$('#slideshow-caption h3').html(title);
$('#slideshow-caption p').html(desc);
$('#slideshow-caption').slideToggle(500);
});


to

$('#slideshow-caption h3').html(title);
$('#slideshow-caption p').html(desc);

it should work.
Reply
Nathan 15 years ago
Great tutorial, simple and easy to follow!
Many thanks
Reply
Tristan Henry M. Soraino 15 years ago
Hey man, thanks for this. How can i make the title and caption for all of the photos be just one... no animation.
Reply
Kevin Liew Admin 15 years ago
You need to tweak this section of code:

//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);
});

to become:
$('#slideshow-caption h3').html(title);
$('#slideshow-caption p').html(desc);
Reply
sup3rg33k 15 years ago
how to add onmouseover=pause & mouseout=play?
Reply
Kevin Liew Admin 15 years ago
It already has one.
Reply