jQuery Photo Slide Show with Slick Caption Tutorial Revisited

Written by Kevin Liew on 16 Dec 2009
266,262 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
jamie 15 years ago
I'm a rookie so please dont kill me too much, i know it pauses when you hover over the image, but how do you add a play and pause button?
Reply
Kevin Liew Admin 15 years ago
you can add this:


$('a.play').click(function () {
clearInterval(timer);
return false;
});

$('a.play').click(function () {
timer = setInterval('gallery()',speed);
return false;
});
Reply
Jamie 15 years ago
thanks man. let me sound like more of a greenhorn, where in the js do put the a.play and where at in the html do i put the play link at, or do i put it in the ul or the div ?
Reply
Raymond 15 years ago
I have some problem..
everything's fine

except on the caption

the white text become transparent too along with the caption
is there a way to make the caption transparent
but not the text


thanks
Reply
raymond 15 years ago
Hi Kevin,
just wondering if there is a way to make the TEXT not transparent

seems like the text followed the opacity of the caption = 0.7..

so if I wanted the text to be opacity 1
and leave the caption with opacity 0.7

is that possible ?
Reply
Kevin Liew Admin 15 years ago
it's possible, you will need to restyle the caption.
This part is from the javascript:

<li id="slideshow-caption" class="caption">
<div class="slideshow-caption-container">
<h3></h3>
<p></p>
</div>
<div class="mask"></div>
</li>

so, set position relative for #slideshow-caption, then set position absolute for slideshow-caption-container and mask (top 0, left 0)... make sure you set the width and height as well. mask's z-index need to be lower than slideshow-caption-container...

after that, change this: $('#slideshow-caption').css({opacity: 0.7, bottom:0});
to $('#slideshow-caption .mask').css({opacity: 0.7, bottom:0});

so the transparent layer is always under the caption.
Reply
Chris 15 years ago
Hi, nice script it's a very easy piece to install.
I've been testing and setting delays to smooth move,
but I'd like my visitors to be able to see the picture just one or two second longer BEFORE the caption appears from bottom.
Is this possible?
Thx
Reply
Kevin Liew Admin 15 years ago
hmm, can't really do that.. because it's using toggle, even if you put delay(), the caption will stay there.
Reply
Annika 15 years ago
Hi, really love this image slider. I have 2 questions.

No1. How do I make the #slideshow-caption start from the right side in the image instead of the left. I would like to have a text-box that do not have the total width of the image and put on the right hand side.

No2: How do I make the #slideshow-caption a little bit more transparent? Some images make it hard to read the white text. I have tried to change this

//Display the caption
$('#slideshow-caption').css({opacity: 1.0, bottom:0});

but nothing happens with the transparancy.

Sorry not english speaking (swedish) so hope you understand what I mean :-)

thanks a lot for a great image gallery.

/ Annika
Reply
Fernando Vadillo 15 years ago
A mi me ha funcionado muy bien
lo unico que pido es como hacer que cuando se le de clic a una imagen me abra el link en otra pagina
Saludos
Reply
Kevin Liew Admin 15 years ago
if validation isn't an issue, the quickest way will be adding target="_blank" in <a href="#">.
Reply
Twa 15 years ago
Hey! So, I was using this code and when I went to run it, it worked perfectly. But, I have the error on one of the parts:

$('ul.slideshow').append('<li id="slideshow-caption" class="caption"><div class="slideshow-caption-container"><h3></h3><p></p></div></li>');

My coding program reads this as an error that "document type does not allow element "li" here"

Please help! Thanks a bunch ahead of time!
Reply
Kevin Liew Admin 15 years ago
you need the CDATA tag to wrap around your javascript code.
Reply
Niels 15 years ago
Is there a way to make it like this:

When you click on the image it goes to the next image?
Reply
Angela 15 years ago
please help me!!! I know is a basic question, but im just learning to use javascript--- :$ my question is what to do with the 3rd step? i mean, i dont know where to paste that code, how i can relate the js with this object? (the gallery) coz i have other elements like buttons with java in the same html! please help me i'll be so thankful!
Reply
Kevin Liew Admin 15 years ago
Just grab the download version and you will able to see the right place to put it.
Reply
Nemoie 15 years ago
Great work!
Has anyone tried to load the content dynamically?
I just can't figure it out myself
Thanks!
Reply
Kevin Liew Admin 15 years ago
Pretty sure you will need server side language to populate the content.
Reply
Ricki 15 years ago
PHP would work a treat at this
Reply
kate 15 years ago
I have a set of three images with the same caption. Is there a way to have the caption only show for the first of the set and no caption at all for the following 2 images?

Thank you!
Reply
Kevin Liew Admin 15 years ago
Sorry, no, you can't do that. You will need some modification.

You need to put if statement, if there isn't content in the title attribute, do not show the caption.
Reply
Rudy 15 years ago
Could you please show me how to use the if statement for not showing a empty caption.
I'm just an newbee in php and scripting and I would like to use your script with no caption on the first slide.
Thanks in advance.
Reply
jones 15 years ago
Ive got this working on firefox and chrome but not IE ... how can i fix it ?
Reply
Kevin Liew Admin 15 years ago
Hey jones, it should work in IE 6-8... does the demo work in your iE?
Reply
Bill 15 years ago
I've got myself a puzzler. I've been using the slideshow for a while with no problems. However, I was just told about a problem involving IE 7 (I know, why do I even care about IE 7 now that there's IE 9. I won't bore you with the reason).

Anyhow, on my site (which is a Drupal site, by the way) we're using Superfish menus and I was just informed that when viewing the site on IE 7, the text labels for the menus do not show and the drop-down functionality stops working. If I disable the slideshow, problem goes away. I'm not very well versed in JQuery so I don't know where to begin to look for a possible conflict.

Any ideas from anyone will be much appreciated. Thanks.
Reply
Kevin 15 years ago
I don't know if you've figured it out yet, but you need to put a z-index on your nav that's higher than 600 i believe. that way it puts your menu over top of the slider.
Reply