jQuery Image Swapping with Fade Effect

Today we are going to cover how to properly change the source of a single image using jQuery. We will also learn how to fade the image out prior to swapping the source, and fade the image back in after the new source has been fully downloaded.

So lets setup a scenario for our script. Lets say we have a bunch of little thumbnails below a larger image. Lets also say our desired functionality here is to have any thumbnail that is clicked on show up as a larger version in the above larger image. Presuming the small thumbnail images have links wrapped around them with a href attribute pointing to the larger version of each thumbnail, we have something to work with.

Demo of scenario in action

To begin, we want to set up new click events for each thumbnails anchor tag and prevent the user from acutely being directed to this image file in the browser.

$('a.thumbnail').click(function(){
    return false;
});

So in the above code we find all anchor elements with a class of “thumbnails” and run over each instance of one. When we find an anchor element that meets this requirement we setup a new click event with an empty anonymous function. Finally in our empty function, we use the “return false;” to prevent the browser from performing the redirect to the image file.

Next we need to gather the clicked anchor tag’s “href” attribute value, and place it into a variable that we will use later on.

$('a.thumbnail').click(function(){
    var src = $(this).attr('href');
    return false;
});

Next, lets prevent from loading images we have already clicked on by comparing our gathered src, to our already set large image’s src, like so:

$('a.thumbnail').click(function(){
    var src = $(this).attr('href');
    if (src != $('img#largeImg').attr('src')) {
    }
    return false;
});

Basically all we are doing is is saying, “If our gathered src is NOT equal to our larger image’s already set ssrc, proceed on to changing the large image’s source”.

Great, now that we have the larger version’s source of our clicked thumbnail, we can proceed on to swapping the image with this new source:

$('a.thumbnail').click(function(){
    var src = $(this).attr('href');
    if (src != $('img#largeImg').attr('src')) {
        $('img#largeImg').stop().animate({opacity:'0'},function(){
                $(this).attr('src',src);
        });
    }
    return false;
});

So here we are pointing the larger image who has and id of “largeImg”, and starting to animate the image’s opacity to 0. Because there is a callback when using jQuery animate, we make use of it to set the source (src=”") of our larger image to our gather thumbnail’s source. We make use of the callback in our animate to prevent the “image source swapping” from happening while the image is still visible.

Next, we want to make sure that our image has fully been downloaded prior to actually making the image indeed visible again. To do this, we make use of the jQuery .load() functionality that will listen to our large image, and perform what we need when the image is ready to be visible.

$('a.thumbnail').click(function(){
    var src = $(this).attr('href');
    if (src != $('img#largeImg').attr('src')) {
        $('img#largeImg').stop().animate({opacity:'0'},function(){
                $(this).attr('src',src);
        }).load(function(){
                $(this).stop().animate({opacity:'1'});
        });
    }
    return false;
});

So as you can see out last step in the .load() callback functionality is to animate our image back to an opacity of 1 again.

Also, note how I use a .stop() prior to any .animate() call. We make use of .stop() prior to .animate() to prevent the animation fires from collecting if the user clicks our thumbnails rapidly.

So our above code is very compact and meets all our requirements of swapping in larger versions of thumbnail sources while performing a fade effect. Drum roll please….

The Problem:

Erik Kraft helped me reproduce the IE error some people might run into with this method. Apparently because we  are making use of the .load() Ajax feature of jQuery and images, IE has a hard time with caching the requests. Because IE caches the requests, any second attempt to load up an already cached image, fails.

The Solution:

Lucky for us, this is a little fix. The solution is to make all requests unique to IE, so no matter if the request is cached or not our script wont fail. We can make each request unique by appending a random number to the end of our src variable, that then gets evaluated by our .load(). Like so:

$('a.thumbnail').click(function(){
    var src = $(this).attr('href');
    if (src != $('img#largeImg').attr('src')) {
        $('img#largeImg').stop().animate({opacity:'0'},function(){
                $(this).attr('src',src+'?'+Math.floor(Math.random()*(10*100)));
        }).load(function(){
                $(this).stop().animate({opacity:'1'});
        });
    }
    return false;
});

So now our images that will be requested from .load(), will be looking something like this:

img/img-three.jpg?691

My random number is between 1 and 100. This random number gives me a 100 to 1 odds that out of my 4 images, the one I click will be a unique request. I will take those odds sir!

Finally, because we have introduced unique requests into the mix, we have a broken our condition that prevents us from loading images we have already clicked. The reason this breaks is cause we are now trying to compare our large image’s source to a unique version of the same url. We can fix this issue by trimming off our unique number at the end of the images url in our condition statement. Like so:

$('a.thumbnails').each(function(){
    $(this).click(function(){
        var src = $(this).attr('href');
        if (src != $('img#largeImg').attr('src').replace(/\?(.*)/,'')) {
            $('img#largeImg').stop().animate({opacity:'0'},function(){
                    $(this).attr('src',src+'?'+Math.floor(Math.random()*(10*100)));
            }).load(function(){
                    $(this).stop().animate({opacity:'1'});
            });
        }
        return false;
    });
});

And that's it. Enjoy!

Demo of script in action

Devin R. Olsen

About Author:

I work as a full time frontend web developer at ISITE Design located in Portland Oregon. I like to teach, share and dabble deep into the digital dark arts of web and game development.

Follow Me:
TwitterFacebookGoogle Plus

21 Responses to “jQuery Image Swapping with Fade Effect”

  1. Simcat says:

    Hi ~ thanks so much for this tutorial and explaining it all so it makes sense. I searched far and wide for something like this and finally landed here! Well done.

  2. Jack White says:

    Great script, especially for a non-coder like me, strictly a front-end web designer. I’m just starting the process of spiffing up an old site and thought you’d like to see how I implemented it:
    http://www.judhartmanngallery.com/lacrossegame.html .

  3. Mark says:

    Spencer, did you ever find a solution to your question? I’m also needing to apply a unique ID to each large image and make it click through to a new window with an even-larger image, and am not sure how to do it.

  4. Bud says:

    This helped me accomplish what a web client needed. Thanks Devin!

    2 comments/requests: A way to set transition time would be a nice addition. Also, the first image fades out before the 2nd one loads, which can be visually distracting, depending on the contrast between the images and the background color. A way to adjust the overlap between fades or make the new image finish fading in before the first one starts fading out would be great.

  5. Nik says:

    I have a little problem with this and I have no doubt its probably me.

    The code fades out the big image but DOES NOT fade in the sub image that was clicked. I was wondering if you had a clue as to what it is I have done wrong? All file paths are correct and have been checked several times.

    I’m using the method without the IE fix. I’ve tried it with as well. Which didn’t solve my problem.

    All in all I’ve checked dozens of sites and yours is the best by far so I’d like to keep at it. Any advice would be great.

    Thanks

  6. Mark says:

    Does it matter that I’m using a newer version of jQuery?

    Does it matter what the div id’s are that the images are in?

    Thanks!

  7. Kyle says:

    Any way to make it faster?

  8. Jez says:

    Great tutorial!

    It would be nice to have a ‘loading’ message or animated gif while the large image is loading.

  9. james says:

    nice and easy solution :)
    it is possible to image swap automatically??

  10. Spencer says:

    Fantastic solution, got it working within minutes! Easiest jQuery tutorial i have ever found, well done Devin!

    A quick question, how would i add a unique link to the large image and pass on the new link once a thumbnail has been clicked, my design requires the large image to open up a larger version in either prettyphoto or simply open up a new page displaying a hires version.

  11. c.harford says:

    To make the image swap on hover (mouseover) I just changed this line:
    $(this).click(function(){
    to this:
    $(this).hover(function(){
    and the hover swap works really well!

    Tested on Windows 7 64bit
    - Chrome 14.0.835.187
    - FF 6
    - IE 9 (64bit)

  12. c.harford says:

    Is it possible to make the image swap work on hover?

  13. Ono Sendai says:

    Hello,

    Your script is great but I was wondering if it would be possible to make it ignore empty links so that it keeps the last displayed image instead of replacing it with a blank one.

    Have no idea how to accomplish that, if you could help me out I’d be very thankful.

    Thnx!

  14. John says:

    this is great, I’ve been looking for something like this for a while.

    the way you’ve explained it is really easy to understand

    thanx

    is it possible to change a ‘background’ image detailed in CSS? by amending $(‘img#largeImg’)

  15. Allen Snook says:

    Works wonderfully – thank you for sharing this jQuery goodie!

  16. eric says:

    Hi, i think it is not good to load the large picture every time,even if it has been cached by the browser. We should add a conditon to see wether the large imgage has been cached or not.It will save a lot of time.

  17. kurius says:

    Very new to JS and finding JQuery.
    Coming from as though, so I foresee a smooth transition (hopefully -_^ ).
    I have a question though, I noticed that if you click a thumb and the larger version loads in, when you click the thumb again, it fades out but doesn’t get replaced. Is there a reason it can’t replace itself?
    Thanks and Very nice, concise, snippet of code here!!

  18. Mehmet says:

    Nice! Talk about keeping it simple and giving a great effect.

  19. I always enjoy feedback from my readers.

Leave a Reply