Preloading images with jQuery

JavascriptJquery

Javascript Problem Overview


I'm looking for a quick and easy way to preload images with JavaScript. I'm using jQuery if that's important.

I saw this here (http://nettuts.com...):

function complexLoad(config, fileNames) {
  for (var x = 0; x < fileNames.length; x++) {
    $("<img>").attr({
      id: fileNames[x],
      src: config.imgDir + fileNames[x] + config.imgFormat,
      title: "The " + fileNames[x] + " nebula"
    }).appendTo("#" + config.imgContainer).css({ display: "none" });
  }
};

But, it looks a bit over-the-top for what I want!

I know there are jQuery plugins out there that do this but they all seem a bit big (in size); I just need a quick, easy and short way of preloading images!

Javascript Solutions


Solution 1 - Javascript

Quick and easy:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(){
        $('<img/>')[0].src = this;
        // Alternatively you could use:
        // (new Image()).src = this;
    });
}

// Usage:

preload([
    'img/imageName.jpg',
    'img/anotherOne.jpg',
    'img/blahblahblah.jpg'
]);

Or, if you want a jQuery plugin:

$.fn.preload = function() {
    this.each(function(){
        $('<img/>')[0].src = this;
    });
}

// Usage:

$(['img1.jpg','img2.jpg','img3.jpg']).preload();

Solution 2 - Javascript

Here's a tweaked version of the first response that actually loads the images into DOM and hides it by default.

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img />').attr('src',this).appendTo('body').css('display','none');
    });
}

Solution 3 - Javascript

Use JavaScript Image object.

This function allows you to trigger a callback upon loading all pictures. However, note that it will never trigger a callback if at least one resource is not loaded. This can be easily fixed by implementing onerror callback and incrementing loaded value or handling the error.

var preloadPictures = function(pictureUrls, callback) {
    var i,
        j,
        loaded = 0;

    for (i = 0, j = pictureUrls.length; i < j; i++) {
        (function (img, src) {
            img.onload = function () {                               
                if (++loaded == pictureUrls.length && callback) {
                    callback();
                }
            };

            // Use the following callback methods to debug
            // in case of an unexpected behavior.
            img.onerror = function () {};
            img.onabort = function () {};

            img.src = src;
        } (new Image(), pictureUrls[i]));
    }
};

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('a');
});

preloadPictures(['http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar', 'http://foo/picture.bar'], function(){
    console.log('b');
});

Solution 4 - Javascript

JP, After checking your solution, I was still having issues in Firefox where it wouldn't preload the images before moving along with loading the page. I discovered this by putting some sleep(5) in my server side script. I implemented the following solution based off yours which seems to solve this.

Basically I added a callback to your jQuery preload plugin, so that it gets called after all the images are properly loaded.

// Helper function, used below.
// Usage: ['img1.jpg','img2.jpg'].remove('img1.jpg');
Array.prototype.remove = function(element) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == element) { this.splice(i,1); }
  }
};

// Usage: $(['img1.jpg','img2.jpg']).preloadImages(function(){ ... });
// Callback function gets called after all images are preloaded
$.fn.preloadImages = function(callback) {
  checklist = this.toArray();
  this.each(function() {
    $('<img>').attr({ src: this }).load(function() {
      checklist.remove($(this).attr('src'));
      if (checklist.length == 0) { callback(); }
    });
  });
};

Out of interest, in my context, I'm using this as follows:

$.post('/submit_stuff', { id: 123 }, function(response) {
  $([response.imgsrc1, response.imgsrc2]).preloadImages(function(){
    // Update page with response data
  });
});

Hopefully this helps someone who comes to this page from Google (as I did) looking for a solution to preloading images on Ajax calls.

Solution 5 - Javascript

This one line jQuery code creates (and loads) a DOM element img without showing it:

$('<img src="img/1.jpg"/>');

Solution 6 - Javascript

$.fn.preload = function (callback) {
  var length = this.length;
  var iterator = 0;

  return this.each(function () {
    var self = this;
    var tmp = new Image();

    if (callback) tmp.onload = function () {
      callback.call(self, 100 * ++iterator / length, iterator === length);
    };

    tmp.src = this.src;
  });
};

The usage is quite simple:

$('img').preload(function(perc, done) {
  console.log(this, perc, done);
});

http://jsfiddle.net/yckart/ACbTK/

Solution 7 - Javascript

I have a small plugin that handles this.

It's called waitForImages and it can handle img elements or any element with a reference to an image in the CSS, e.g. div { background: url(img.png) }.

If you simply wanted to load all images, including ones referenced in the CSS, here is how you would do it :)

$('body').waitForImages({
    waitForAll: true,
    finished: function() {
       // All images have loaded.
    }  
});

Solution 8 - Javascript

this jquery imageLoader plugin is just 1.39kb

usage:

$({}).imageLoader({
    images: [src1,src2,src3...],
    allcomplete:function(e,ui){
        //images are ready here
        //your code - site.fadeIn() or something like that
    }
});

there are also other options like whether you want to load the images synchronously or asychronously and a complete event for each individual image.

Solution 9 - Javascript

you can load images in your html somewhere using css display:none; rule, then show them when you want with js or jquery

don't use js or jquery functions to preload is just a css rule Vs many lines of js to be executed

example: Html

<img src="someimg.png" class="hide" alt=""/>

Css:

.hide{
display:none;
}

jQuery:

//if want to show img 
$('.hide').show();
//if want to hide
$('.hide').hide();

Preloading images by jquery/javascript is not good cause images takes few milliseconds to load in page + you have milliseconds for the script to be parsed and executed, expecially then if they are big images, so hiding them in hml is better also for performance, cause image is really preloaded without beeing visible at all, until you show that!

Solution 10 - Javascript

A quick, plugin-free way to preload images in jQuery and get a callback function is to create multiple img tags at once and count the responses, e.g.

function preload(files, cb) {
    var len = files.length;
    $(files.map(function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

preload(["one.jpg", "two.png", "three.png"], function() {
    /* Code here is called once all files are loaded. */
});
​    ​

Note that if you want to support IE7, you'll need to use this slightly less pretty version (Which also works in other browsers):

function preload(files, cb) {
    var len = files.length;
    $($.map(files, function(f) {
        return '<img src="'+f+'" />';
    }).join('')).load(function () {
        if(--len===0) {
            cb();
        }
    });
}

Solution 11 - Javascript

Thanks for this! I'd liek to add a little riff on the J-P's answer - I don't know if this will help anyone, but this way you don't have to create an array of images, and you can preload all your large images if you name your thumbs correctly. This is handy because I have someone who is writing all the pages in html, and it ensures one less step for them to do - eliminating the need to create the image array, and another step where things could get screwed up.

$("img").each(function(){
    var imgsrc = $(this).attr('src');
    if(imgsrc.match('_th.jpg') || imgsrc.match('_home.jpg')){
	  imgsrc = thumbToLarge(imgsrc);
	  (new Image()).src = imgsrc;	
    }
});

Basically, for each image on the page it grabs the src of each image, if it matches certain criteria (is a thumb, or home page image) it changes the name(a basic string replace in the image src), then loads the images.

In my case the page was full of thumb images all named something like image_th.jpg, and all the corresponding large images are named image_lg.jpg. The thumb to large just replaces the _th.jpg with _lg.jpg and then preloads all the large images.

Hope this helps someone.

Solution 12 - Javascript

    jQuery.preloadImage=function(src,onSuccess,onError)
    {
    	var img = new Image()
    	img.src=src;
    	var error=false;
    	img.onerror=function(){
    		error=true;
    		if(onError)onError.call(img);
    	}
    	if(error==false)	
    	setTimeout(function(){
    		if(img.height>0&&img.width>0){ 
    			if(onSuccess)onSuccess.call(img);
    			return img;
    		}	else {
    			setTimeout(arguments.callee,5);
    		}	
    	},0);
    	return img;	
    }
    
    jQuery.preloadImages=function(arrayOfImages){
    	jQuery.each(arrayOfImages,function(){
    		jQuery.preloadImage(this);
    	})
    }
 // example   
    jQuery.preloadImage(
    	'img/someimage.jpg',
    	function(){
    		/*complete
    		this.width!=0 == true
    		*/
    	},
    	function(){
    		/*error*/
    	}
    )

Solution 13 - Javascript

I use the following code:

$("#myImage").attr("src","img/spinner.gif");

var img = new Image();
$(img).load(function() {
	$("#myImage").attr("src",img.src);
});
img.src = "http://example.com/imageToPreload.jpg";

Solution 14 - Javascript

I would use an Manifest file to tell (modern) web browsers to also load all relevant images and cache them. Use Grunt and grunt-manifest to do this automatically and never worry again about preload scripts, cache invalidators, CDN etc.

https://github.com/gunta/grunt-manifest

Solution 15 - Javascript

function preload(imgs) {
	$(imgs).each(function(index, value) {
		$('<img />').attr('src', value).appendTo('body').css('display', 'none');
	});
}

.attr('src',value) not .attr('src',this)

just to point it out :)

Solution 16 - Javascript

This works for me even in IE9:

$('<img src="' + imgURL + '"/>').on('load', function(){ doOnLoadStuff(); });

Solution 17 - Javascript

I wanted to do this with a Google Maps API custom overlay. Their sample code simply uses JS to insert IMG elements and the image placeholder box is displayed until the image is loaded. I found an answer here that worked for me : https://stackoverflow.com/a/10863680/2095698 .

$('<img src="'+ imgPaht +'">').load(function() {
$(this).width(some).height(some).appendTo('#some_target');
});

This preloads an image as suggested before, and then uses the handler to append the img object after the img URL is loaded. jQuery's documentation warns that cached images don't work well with this eventing/handler code, but it's working for me in FireFox and Chrome, and I don't have to worry about IE.

Solution 18 - Javascript

I usually use this snippet of code on my projects for the loading of the images in a page. You can see the result here https://jsfiddle.net/ftor34ey/

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<img src="https://live.staticflickr.com/65535/50020763321_d61d49e505_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50021019427_692a8167e9_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50020228418_d730efe386_k_d.jpg" width="100" />
<img src="https://live.staticflickr.com/65535/50020230828_7ef175d07c_k_d.jpg" width="100" />

<div style="background-image: url(https://live.staticflickr.com/65535/50020765826_e8da0aacca_k_d.jpg);"></div>
<style>
	.bg {
		background-image: url("https://live.staticflickr.com/65535/50020765651_af0962c22e_k_d.jpg");
	}
</style>
<div class="bg"></div>

<div id="loadingProgress"></div>

The script save in an array all the src and background-image of the page and load all of them.

You can see/read/show the progress of the loading by the var loadCount.

let backgroundImageArray = [];

function backgroundLoading(i) {

	let loadCount = 0;

	let img = new Image();
	$(img).on('load', function () {

		if (i < backgroundImageArray.length) {

			loadCount = parseInt(((100 / backgroundImageArray.length) * i));
			backgroundLoading(i + 1);

		} else {

			loadCount = 100;
			// do something when the page finished to load all the images
			console.log('loading completed!!!');
			$('#loadingProgress').append('<div>loading completed!!!</div>');

		}

		console.log(loadCount + '%');
		$('#loadingProgress').append('<div>' + loadCount + '%</div>');

	}).attr('src', backgroundImageArray[i - 1]);

}

$(document).ready(function () {

	$('*').each(function () {

		var backgroundImage = $(this).css('background-image');
		var putInArray = false;

		var check = backgroundImage.substr(0, 3);

		if (check == 'url') {

			backgroundImage = backgroundImage.split('url(').join('').split(')').join('');
			backgroundImage = backgroundImage.replace('"', '');
			backgroundImage = backgroundImage.replace('"', '');

			if (backgroundImage.substr(0, 4) == 'http') {
				backgroundImage = backgroundImage;
			}
			putInArray = true;

		} else if ($(this).get(0).tagName == 'IMG') {

			backgroundImage = $(this).attr('src');
			putInArray = true;

		}

		if (putInArray) {
			backgroundImageArray[backgroundImageArray.length] = backgroundImage;
		}

	});

	backgroundLoading(1);

});

Solution 19 - Javascript

5 lines in coffeescript

array = ['/img/movie1.png','/img/movie2.png','/img/movie3.png']

$(document).ready ->
  for index, image of array
    img[index] = new Image()
    img[index].src = image

Solution 20 - Javascript

For those who know a little bit of actionscript, you can check for flash player, with minimal effort, and make a flash preloader, that you can also export to html5/Javascript/Jquery. To use if the flash player is not detected, check examples on how to do this with the youtube role back to html5 player:) And create your own. I do not have the details, becouse i have not started yet, if i dont forgot, i wil post it later and will try out some standerd Jquery code to mine.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionView Question on Stackoverflow
Solution 1 - JavascriptJamesView Answer on Stackoverflow
Solution 2 - JavascriptDennis RongoView Answer on Stackoverflow
Solution 3 - JavascriptGajusView Answer on Stackoverflow
Solution 4 - JavascriptDaveView Answer on Stackoverflow
Solution 5 - JavascriptrkcellView Answer on Stackoverflow
Solution 6 - JavascriptyckartView Answer on Stackoverflow
Solution 7 - JavascriptalexView Answer on Stackoverflow
Solution 8 - JavascriptalzclarkeView Answer on Stackoverflow
Solution 9 - JavascriptitsmeView Answer on Stackoverflow
Solution 10 - JavascriptizbView Answer on Stackoverflow
Solution 11 - JavascriptdmgigView Answer on Stackoverflow
Solution 12 - JavascriptAlexView Answer on Stackoverflow
Solution 13 - JavascriptCristanView Answer on Stackoverflow
Solution 14 - JavascriptChristian LandgrenView Answer on Stackoverflow
Solution 15 - JavascriptWhisherView Answer on Stackoverflow
Solution 16 - JavascriptZymotikView Answer on Stackoverflow
Solution 17 - JavascriptbwinchesterView Answer on Stackoverflow
Solution 18 - JavascriptFrancesco OrsiView Answer on Stackoverflow
Solution 19 - JavascriptGuy MoritaView Answer on Stackoverflow
Solution 20 - JavascriptPeter GruppelaarView Answer on Stackoverflow