Smoother background fading with jquery

I’ve put together a crude example of some jquery that fades some overlapping divs that containing background images. However, it feels really clunky in both Safari and Firefox on my machine so I guessing Im not using the right approach.

Example here

$(function() {

	
	 $('#nav_one').hover(function(e) {
			$('#image_one').fadeIn("slow");
				$('#image_two').fadeOut("slow");
				

    });
	
	 $('#nav_two').hover(function(e) {
                $('#image_one').fadeOut("slow");
			$('#image_two').fadeIn("slow");
				
    });

I think it is partly because as the images fade / appear at the same time so you see the background briefly.

If I were using flash I would leave one image in place while until the fade in was complete. How can I achieve this using jquery?

Using Javascript to mess with the opacity of an element can be quite performance-heavy. I would recommend that you use CSS3 transitions in browsers that support the feature. there are several articles out there that walk through the process, and just to name two:

  1. http://www.w3.org/TR/css3-transitions/
  2. http://net.tutsplus.com/tutorials/html-css-techniques/css-fundametals-css-3-transitions/

I’ll certainly look into it but I haven’t noticed the same problem on “slideshows”.

Would this be because of the size of the images? or the fact that they are background images on elements? Could I use actual images instead?

And how do I get around the timing issue I mentioned?

Sorry for firing lots of questions!

EDIT : I need to support IE 7 at least so CSS3 transitions are out :frowning:

As far as Javascript performance on images is concerned, here are some rules you should bear in mind:

  • Fading smoothness will be lost as the image byte size increases
  • Fading background images will consume far more resources than inline images
  • Slower (JS) transitions will have a negative impact on the smoothness of the fade

You can indeed use inline images instead of backgrounds, but I would recommend doing CSS3, and falling back to JS for browsers that do not support it (that’s how I do it). You can also the (IE only) DXImageTransform Fade filter (http://msdn.microsoft.com/en-us/library/ms532990(v=vs.85).aspx).

As for your timing issue, you can use code like this: $(‘#image_one’).delay(800).fadeIn(1000);

In this example, a fade in of 1 second will occur after a delay of 800ms.

Thanks for you help Tommi.

I think what Im trying to do with the delay is not actually assign a time to it — rather activate the outgoing fade ‘after’ the incoming fade has complete.

Something like


 $('#nav_one').hover(function(e) {
			$('#image_one').fadeIn("slow");
 // when complete               $('#image_two').fadeOut("fast");
			  });

Using jQuery’s animate method, you can do something like this:
$(‘#image_one’).animate({ opacity:0 }, ‘slow’, function() {
$(‘#image_two’).animate({ opacity:1 }, ‘slow’);
});

This will execute the animation, then execute the callback function when the animation is complete.

Using jquery’s animate method, you can do something like this:
$(‘#item1’).animate({ opacity: 0 }, ‘slow’, function() { $(‘#item2’).animate({ opacity: 1 }, ‘slow’); });

Excellent! So I could alter the z-index also using this method if I wanted multiple “layers”?

Hmm. Might need some sort of stacking. This is getting more complicated by the moment! Shame, I wouldn’t have a problem with doing this in flash.

Thanks again for you help.

To save yourself the aggravation of fiddling with z-index, you can simply modify the visibility (or display property) of your images, to hide the one that is faded out, for example (using visibility):
$(‘#item1’).animate({ opacity: 0 }, ‘slow’, function() { $(‘#item2’).css({ visibility: ‘visible’})animate({ opacity: 1 }, ‘slow’); });

Do bear in mind that if you use visibility, the hidden element most start off with a css visibility property of hidden. I you use display, the hidden element most start off with a css display property of none.

I have been working on another approach.

I have to use z-index in order to ‘stack’ the images. I want to bring the selected image to the front BEFORE fading it in. This was you can see the image that is under it to be seen through the image that is fading in.

$('#link01').mouseover(function() {
		  $('#image01').css('zIndex', 100).animate({opacity: 1}, 'slow', function() {
							// then do this
							$('#image02').animate({opacity: 0}, 'fast').css('zIndex', 1);
							$('#image03').animate({opacity: 0}, 'fast').css('zIndex', 1);
							
		  });
	});

However, my switching of z-index seems to be ignored until the animation is complete - rather than being done first. Anyone see how I might fix this?