jQuery Here is a small code snippet I use for preloading images for mouseovers. It uses $(window).bind(‘load’, function() {...}) to wait until all page elements have finished loading. This includes all images. If you use $(document).ready() it would start preloading images while other elements are still loading. This will make rest of the page feel slow.

Code below searches for all images with class hover. Then it adds _on to image name and pushes it to preload queue. When page has finished loading, images in preload queue get loaded. Loading happens sequentially one by one. Thus reducing stress to server.

Preloading code is based on mailing list post by Luke Lutman. Note that currently this code throws stack overflow with IE when there is more than 15 images to be preloaded. I am currently working on version which avoids this problem.

$(window).bind('load', function() {
    var preload = new Array();
    $(".hover").each(function() {
        s = $(this).attr("src").replace(/\.(.+)$/i, "_on.$1");
        preload.push(s)
    });
    var img = document.createElement('img');
    $(img).bind('load', function() {
        if(preload[0]) {
            this.src = preload.shift();
        }
    }).trigger('load');
});

After preloading I use following code to apply mouseovers. If there is image already which ends with string _on mouseover is removed.

$(document).ready(function() {
    $(".hover").each(function() {
        if ($(this).attr("src").match(/_on\.(.+)$/i)) {
            $(this).removeClass("hover");
        }
    });
    $(".hover").hover(function() {
        s = $(this).attr("src").replace(/\.(.+)$/i, "_on.$1");
        $(this).attr("src", s);
    }, function() {
        s = $(this).attr("src").replace(/_on\.(.+)$/i, ".$1");
        $(this).attr("src", s);
    });
});

For those who want to test. You can download snippet here.

UPDATE: You might also want to check how to lazy load images


18 Responses to “Preload Images Sequentially With jQuery”

  1. benjamin sapp says:

    thanks for this. it saved me some time.

  2. Mika Tuupola says:

    Glad I could help :)

  3. Sun says:

    this is great! thanks for sharing. :-)

  4. pelle says:

    hi

    i tried out your example above but had some problems with images with absolute urls (which normally should be used for cache reasons)

    anyway my reg exp. skills are limited so i went for the jquery irc:

    pelle_: hi – does anyone have an online example of manipulating a string in jquery – more specific to insert a “_on” to the following string “http://127.0.0.1/bn_flag_english.gif” so it looks like “http://127.0.0.1/bn_flag_english_on.gif” i tried with <string>.replace(/\.(.+)$/i, “_on.$1”) seen @ http://www.appelsiini.net/~tuupola/823/sequentially-preloading-images – but this inserts the “_on” the wrong place “http://127_on.0.0.1/bn_flag_english.gif” ........ thanks for any hints

    and got the following solution/suggestion:

    bidioule_: .replace(/\.([^.]+)$/i,”_on.$1”)

    this works for me

    //

    pelle

  5. Mika Tuupola says:

    Good catch. Thanks!

  6. matt says:

    thanks for sharing, i’ve modified for my needs and it works like a charm! much better than other solutions i’ve been looking at. :)

  7. Mika Tuupola says:

    Thanks! This code snippet is also part of my everlasting quest on how to make websites (feel) faster.

  8. ben says:

    How would one use a placeholder image with this? I’m trying to show a loading gif until all the images are loaded.

  9. Mika Tuupola says:

    ben: Basically you would change the src attribute of original image to placeholder. Then create new image element with original src attribute. When load event of this new img element triggers you then change src of original image back to original src.

    However I do not quite understand what you are trying to achieve. You usually preload images which are not visible. Is something like Lazy Loading what you are after?

  10. Timur I. Alhimenkov says:

    Good work! Thank you very much! I always wanted to write in my site something like that. Can I take part of your post to my site? Of course, I will add backlink?

    Sincerely, Reader

  11. Mika Tuupola says:

    Timur: Sure go ahead!

  12. Dave says:

    Wouldn’t this do to preload the images?

    $(window).bind('load', function() {
        $("img.hover").each(function() {
            $("<img/>").src(
              this.src.replace(/\.(.+)$/i, "_on.$1")
            );
        });
    });
    

    Also, you might want to do the image toggling in css instead of changing the src attribute, since that gives you the ability to add a hover class to any type of element and define its look with a style.

  13. Mika Tuupola says:

    Yes it would. My example loads sequentially meaning one by one, waiting for previous preloading to finish before starting next one. This is desirable in some cases.

  14. Peter says:

    Hi there, do you have a working live example where you use this code? I don’t get it work, and i find it easiest to see it running in a website to figure what the problem is… Thanks Peter

  15. bolas chinas says:

    Thanks, this tip was a great help to solve a problem that came to dragging my site from time. best regards fr

  16. Mika Tuupola says:

    Peter: Sorry no example page at the moment. I will put it into my TODO list.

  17. jQuery says:

    This is a great article, but if you just want to preload images I found this article about preloading images with jquery very detailed and useful.

    Hope it will help one of you guys too.

  18. supermegapollo says:

    Hi, here is my approach, hope it helps.

    It was the only think that actually worked for me when using jquery-1.3.2 and carousel.js (http://interface.eyecon.ro/docs/carousel) that was failing in FF3 and Safari4 on both winxp and osx when the images where not fully loaded.

    var imgnum = 0; var imgldd = 0; $(document).ready(function(){ imgnum = $('#carousel img').length; $('#carousel img').load(function(){ imgldd++; if(imgnum == imgldd){ $('#cargando').css('visibility', 'hidden'); $('#carousel img').css('visibility', 'visible'); $('#carousel').Carousel( { itemWidth: 160, itemHeight: 110, itemMinWidth: 160, items: 'a', reflections: 0, rotationSpeed: 1.8 } ); } }); });

Leave a Reply



(will not be published)



(you can use Textile for formatting)