Preloading Images with jQuery
Update: This solution has been updated to a better solution that is explained in detail.
The solution is to preload the images so they display when you want them to. This is pretty simple with jQuery.
jQuery.preloadImages = function() { for(var i = 0; i<arguments.length; i++) { jQuery("<img>").attr("src", arguments[i]); } }
You can insert this code in a separate javascript file and load it before you do any of your lifting or, as I did for Geeks and God, you can throw it at the top of your javascript file where you are doing your effects.
After including this script you need to tell it what images to preload. To do this the code is simply:
$.preloadImages("image1.gif", "/path/to/image2.png", "some/image3.jpg");
This will run when the document is ready to accept javascript (just like using .ready() but shorter). Just load the function up with comma separated images.
Comments
#1 thanks!
Hey just wanted to thank you for posting this -- now I can jettison the crappy old preloader I have been borrowing from Dreamweaver...
#2 Thanks
I used this as well. Thank you, clean and simple.
#3 Nice Shot!
hello Matt,
great mixture of Jquery. I am using both Prototype and Jquery due to some reasons and was thinking to use prototype for image pre-loading. I am happy that you solved my problem using Jquery, Thanks for it :)
#4 Image preloader detailed explanation
Hi and thanks for this post. I came to this page through google.
I also found this article on preloading images with jQuery that describes the proccess in more detail. It's a good article for jQuery newbies.
#5 Thanks. Now I can use this
Thanks. Now I can use this on my new Nerds and Satan Website!
#6 Thanks, small and simple
That worked like a charm,
Opera does not preload images that are in img tags which are hidden (dispaly:none) thus a preloading is needed (often times)
#7 Thank you.
Thanks, looks like it works just fine.
#8 Anyone got it working on IE?
Doesn't seem to work on IE (neither 6 nor 7). Anyone has it working on IE?
#9 Yeah
I've used this in IE for some time. Since the jQuery 1.0.4 days. I've seen it work in IE6 and IE7 on multiple sites. The must be something else going on here.
#10 You're supposed to use self
You're supposed to use self closing tags with jQuery, not doing it can lead to weird troubles. I mean instead of .
But even with this properly handled, it seems ie6 doesn't preload.
#11 You're supposed to use self
You're supposed to use self closing tags with jQuery, not doing it can lead to weird troubles. I mean <img/> instead of <img>.
But even with this properly handled, it seems ie6 doesn't preload.
#12 Awesome
Just wanted to thank you for this, works like a charm !
#13 Great preloader!
Ditto to jettisoning the DW rubbish. Thank you Matt!
#14 Thanks
Thanks for this simple and clean solution Matt. I was looking for something to preload a status bar and this fit the bill.
Cheers!
#15 Small change
Hi, this makes it little bit quicker and also a bit more flexible. You can pass on array or list of images to preload.
var prelod = ['image1.gif', 'image2.gif']; $.preloadImages(preload); $.preloadImages('image1.gif', 'image2.gif'); jQuery.preloadImages = function() { var a = (typeof arguments[0] == 'object')? arguments[0] : arguments; for(var i = a.length -1; i > 0; i--) { jQuery("<img>").attr("src", a[i]); } }#16 Erroneous while condition
Hi there, you've made some nice improvements to the original snippet. However, your while condition is off. Instead of 'i > 0', you need 'i > -1'. Otherwise, the first image in the list will never be pre-loaded.
Otherwise, nice work! (to you, the OP, and everyone! :) )
-Rich
#17 You can also use the load()
You can also use the load() function if you need a callback:
var _images = ['image1.jpg','image2.jpg'];
$.each(_images,function(e) {
$(new Image()).load(function() {
alert($(this).attr('src') + 'has loaded!');
}).attr('src',this);
});
#18 cumulative onLoad of all images
good idea.. I added a counter to ensure all said images were loaded before calling begin():
var _images = ["img1.jpg", "image2.jpg", "imij3.jpg"]; var gotime = _images.length; $.each(_images,function(e) { $(new Image()).load(function() { if (--gotime < 1) begin(); }).attr('src',this); });Note: there's no error checking.. those images better exist or your begin() ain't gonna..
#19 Thanks
Works good. This helped me with my interval problem :)
#20 Rewrite
I couldn't get your version to work for some reason. FireBug did list the images in its net pane showing them downloading, but when I mouseovered the element I wanted to use the preloaded images on it just loaded them again. The following rewrite seems to work fine, don't ask me why though!
jQuery.preload = function()
{
jQuery.each (arguments,function (e)
{
jQuery ('');
});
}
#21 Damn, the actual line that
Damn, the actual line that injects the images seems to have been censored! Lets try that again:
jQuery.preload = function() { jQuery.each (arguments,function (e) { jQuery ('<img src="' + this + '" />'); }); }#22 thanks
very thanks for examples
#23 RE: - Preload images jQuery cycle issue
Here's how we got around the issue of preloading images:
We used setInterval to call a function iteratively every 1 second to check if all the images have loaded:
var vCycleImages = setInterval("setImgCycleStatus()", 1000);
$(function() {
$('#fadeCenter').cycle();
$('#fadeCenter').cycle('stop');
});
function setImgCycleStatus() {
if ($.preloadImages("pic1", "pic2", "pic3", "pic4")){
$('#fadeCenter').cycle({
speed: 500,
timeout: 8000,
delay: -5000,
startingSlide: 0
});
clearInterval(vCycleImages);
}
}
jQuery.preloadImages = function() {
var bImgLoaded = true;
for(var i = 0; i < arguments.length; i++){
if (document.getElementById(arguments[i]).complete == false) {
bImgLoaded = false;
}
}
return bImgLoaded;
}
Hope this helps.
Samir Pipalia
Pipalia Software House
http://www.pipalia.co.uk
#24 Example
If anyone is looking for an example, for the previously mentioned solution, please visit our customer's site at http://www.cefinaDesign.co.uk
#25 I ended up using a variation
I ended up using a variation of Samir's sample. Instead of listing out each id for the image though I used the selector of any image in the div#slideshow.
var vCycleImages = setInterval("setImgCycleStatus()", 1000); function setImgCycleStatus() { if ($.preloadImages($("#slideshow img"))) { $('#slideshow').cycle({ delay: 1000, speed: 1000 }); clearInterval(vCycleImages); } } jQuery.preloadImages = function() { var bImgLoaded = true; for (var i = 0; i < arguments.length; i++) { if (arguments[i].complete == false) { bImgLoaded = false; } } return bImgLoaded; }#26 Slight Modification
I add to make a slight modification to my script for it to work correctly. See below on line 14.
1. var vCycleImages = setInterval("setImgCycleStatus()", 1000); 2. 3. function setImgCycleStatus() { 4. if ($.preloadImages($('#slideshow img'))) { 5. $('#slideshow').cycle({ delay: 1000, speed: 1000 }); 6. clearInterval(vCycleImages); 7. } 8. } 9. 10. jQuery.preloadImages = function() { 11. var bImgLoaded = true; 12. 13. for (var i = 0; i < arguments.length; i++) { 14. if (arguments[i].attr("complete") == false) { 15. bImgLoaded = false; 16. } 17. } 18. return bImgLoaded; 19. }#27 Last Time
This is another variation of the above posts that I much prefer. It's all contained in one function and seems easier to follow.
$(document).ready(function() { vCycleImages = setInterval(function() { var bImgLoaded = true; var images = $("#slideshow img"); for (var i = 0; i < images.length; i++) { var img = images[i]; if (img.complete == false) bImgLoaded = false; } if (bImgLoaded) { $("#slideshow").cycle({ delay: 1000, speed: 1000 }); clearInterval(vCycleImages); } }, 1000); });#28 That's great improvement
That's great improvement over my code Deran - thanks for submitting your tip.
#29 Where be the recursive event driven one?
real quick copy and paste from some code I wrote....no comments or explanations sorry
function loadImage()
{
if(loadGallery.DATA.length>0)
{
$(new Image()).load(function()
{
loadGallery.DATA.reverse().pop();
loadGallery.DATA.reverse();
console.log(loadGallery.DATA[0][9]);
loadImage();
}).attr('src','/Gallery' + loadGallery.DATA[0][9]);
}
else
{
return;
}
}
#30 loading images, creating automatic array
This is excellent code...I am just wondering if i can upload images from a file (specified) and automatically creating an array based on a user click on link?
for example:
user clicks on link
jQuery compares the link and uploads images from link related file, creates array automatically based on a maximum number of images for display on a page that is #content based.
is this possible?
eyveneena
#31 Great comments
Great topic and the comments are also cool with helpful code hints.
Thank you all.
#32 Thanks
This snippet is both useful and clean, I never thought of writing it so simply. Thanks
#33 Thanks for the post
Wow, I and my Google Notebook > Code Snippets > JavaScript thank you for this post! Quick and dirty, no verbose explanation, this was exactly what I was looking for. Thanks for posting this Matt, you saved me a ton of time just now and will in the future.
Thank you thank you!
#34 What if the user start
What if the user start clicking around before the preloading has complete? Is there a way to block ui with some graphic indicator? Thanks.
#35 Use jQuery user interface locker plugin
@Nemo, you can use jQuery uiLock plugin to block user interactions.
PS. Thanks for an article.
#36 Preloading images in a crossfader
Hi,
I am a total newb here.. I just managed to get this working with a couple of wordpress posts, but I cant seem to get the preloading to work.
This is my script:
How can I preload this with a small preloading anim ?
#37 FYI, it is way more efficient
FYI, it is way more efficient to use:
instead of
There is a 20 second difference between the two methods if I have a list of 10000 images.
#38 Preload with slideshow
Thanks for the cool Ideas. But I can't realy get them up and running.
I used the code fro, #27 Last Time and I wanted to include a slideshow with a fade. But the images will not load as a preloader.
Can anyone help me?
$(document).ready(function() {
vCycleImages = setInterval(function() {
var bImgLoaded = true;
var images = $("#slideshow img");
for (var i = 0; i < images.length; i++) {
var img = images[i];
if (img.complete == false)
bImgLoaded = false;
}
if (bImgLoaded) {
$("#slideshow").cycle({ delay: 1000, speed: 1000 });
clearInterval(vCycleImages);
}
}, 1000);
});
function slideSwitch() {
var $active = $('#slideshow IMG.active');
if ( $active.length == 0 ) $active = $('#slideshow IMG:last');
var $next = $active.next().length ? $active.next()
: $('#slideshow IMG:first');
$active.addClass('last-active');
$next.css({opacity: 0.0})
.addClass('active')
.animate({opacity: 1.0}, 1000, function() {
$active.removeClass('active last-active');
});
}
$(function() {
setInterval( "slideSwitch()", 5000 );
});
#39 valid html with document.createElement
I changed one line to:
jQuery(document.createElement("img")).attr("src", arguments[i]);
Using document.createElement is better when validating, if you use xhtml. The "" string causes validation errors.
#40 First time my example code
First time my example code did not show up. I'll try again.
The
"<img>"string causes validation errors because it's seen as markup.