Simple jQuery image crossfade
I wanted a simple jQuery crossfade effect for an image cycler last week, and surprisingly couldn’t find anything suitable. So I ended up writing my own, and here it is. Tested in IE6/7/8, Firefox 3, Chrome, Opera 9/10, Safari 4, all on Windows XP, and Safari 5 on Mac OS X/Snow Leopard.
The demo
The code
Here’s the necessary css – just to show the z-index and positioning – you’ll need to add some more to position as required:
#portfolio_cycler{position:relative;}
#portfolio_cycler img{position:absolute;z-index:1}
#portfolio_cycler img.active{z-index:3}
And here’s the javascript:
function cycleImages(){
var $active = $('#portfolio_cycler .active');
var $next = ($('#portfolio_cycler .active').next().length > 0) ? $('#portfolio_cycler .active').next() : $('#portfolio_cycler img:first');
$next.css('z-index',2);//move the next image up the pile
$active.fadeOut(1500,function(){//fade out the top image
$active.css('z-index',1).show().removeClass('active');//reset the z-index and unhide the image
$next.css('z-index',3).addClass('active');//make the next image the top one
});
}
$(document).ready(function(){
// run every 7s
setInterval('cycleImages()', 7000);
})
The logic
All the images are loaded with the page and positioned absolutely on top of each other, all with z-index=1. One image is initially set with a class of “active”, which is positioned on the top of the stack with z-index = 3.
Then, using jQuery, I’m identifying the active image, and then the next image down. I’m doing this via the jQuery .next() method. If there isn’t a next image – if we’re at the end of the images – I’m selecting the first image instead using .first().
Now, once I’ve identified the next image, I’m assigning z-index=2 to this so it’s the second image down in the pile – and hence is visible when the top image fades out.
Then, I’m fading out the active image. When this completes there’s a few things to do. First, I’m setting the z-index of the active image (now faded out) back to z-index=1. Then, I’m reversing the fade by using the show() method. It won’t be visible now because of the z-index. Finally, I’m removing the active class. Effectively, I’m putting this image back into the bottom pile.
Nearly there. Then, with the next image, which is now on top anyway, I’m assigning z-index=3, and then adding the active class to this image.
Finally, all of this code is sitting in a function which I’m calling every seven seconds via setInterval().
This is neat. I am having some issues reproducing it. The way you set it up…it doesn’t matter how many images in the stack right?
Hi David
No – it should work fine however many images are stacked up.
Brilliant, Simon! I had accidently removed my js line in the head when got rid of an old rotator script that was too bloated. Thanks for making something simple…well, simple!
Hello Simon, thank you! I’ve found what I need, thanks a lot.
What is the correct way to have two of those crossfade effects on one page?
Hi Katka
The revised html needs to be:
function cycleImages(){ $('.cycler').each(function(){ var $active = $(this).find('.active'); var $next = ($(this).find('.active').next().length > 0) ? $(this).find('.active').next() : $(this).find('img:first'); $next.css('z-index',2);//move the next image up the pile $active.fadeOut(1500,function(){//fade out the top image $active.css('z-index',1).show().removeClass('active');//reset the z-index and unhide the image $next.css('z-index',3).addClass('active');//make the next image the top one }); }); } $(document).ready(function(){ // run every 7s setInterval('cycleImages()', 7000); })with each div assigned a class of
cyclerinstead of the idportfolio_cycleras in the main example.Thank you Simon!
Great script. Very helpful. I modified it to use divs instead of just images and also set it to run when an item is clicked rather than on a timer so it could be used as a product image gallery with sets of images per product. Thanks for getting me started.