Need some help?

I'm usually available for small jobs or problem solving with jQuery or css. Just get in touch.

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

Hoverfly on a green leaf Fly on a pink flower Insect on a leaf Fly

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().

7 responses to “Simple jQuery image crossfade”

  1. David says:

    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?

  2. Simon says:

    Hi David

    No – it should work fine however many images are stacked up.

  3. Pam Hamilton says:

    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!

  4. Kate says:

    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?

  5. Simon says:

    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 cycler instead of the id portfolio_cycler as in the main example.

  6. Kate says:

    Thank you Simon!

  7. Erik says:

    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.

Useful? Interesting? Leave me a comment