87

Sometimes images take some time to render in the browser. I want to show a busy image while the actual image is downloading, and when the image is downloaded, the busy image is removed and the actual image should be shown. How can I do this with JQuery or any javascript?

MastaBaba
  • 1,085
  • 1
  • 12
  • 29
Thomas
  • 33,544
  • 126
  • 357
  • 626

5 Answers5

164

Just add a background image to all images using css:

img {
  background: url('loading.gif') no-repeat;
}
Gerben
  • 16,747
  • 6
  • 37
  • 56
  • It should help in ADF Applications where javascript exceution is nondeterministic due to partial page rendering. I will give a try for sure :-). – Tapas Bose Jul 13 '13 at 20:01
  • 26
    Hmm, if an image has transparent areas, then background still can be seen after the image has already loaded. – JustAMartin Aug 06 '13 at 16:27
  • 4
    @Martin transparent images, indeed, won't work. – Gerben Aug 06 '13 at 19:45
  • 1
    Although a JS Script when page loads to take away the background image will work. – MasterT Mar 19 '16 at 18:28
  • 1
    this doesn't work for responsive images, you need to set image size in order to show the background – dima Mar 17 '17 at 17:37
  • If you want the background image to take up the full size of the image you should add `background-size: 100% 100%;` – Kyle Krzeski Jul 06 '17 at 14:54
  • @WilliamHampshire You can also use `background-size: cover;` or `background-size:contain;` if you want to preserve the aspect ratio of the image, but still have it full-size. – Gerben Jul 06 '17 at 18:10
101

You can do something like this:

// show loading image
$('#loader_img').show();

// main image loaded ?
$('#main_img').on('load', function(){
  // hide/remove the loading image
  $('#loader_img').hide();
});

You assign load event to the image which fires when image has finished loading. Before that, you can show your loader image.

Akhilesh B Chandran
  • 6,523
  • 7
  • 28
  • 55
Sarfraz
  • 377,238
  • 77
  • 533
  • 578
  • I have also used this technique and it works really well. Just remember to handle the error and abort cases... – will Jan 26 '11 at 04:54
  • @WearetheWorld add handler for the error event. you can do something like `$(img).load(handler).error(handler)`. @see http://api.jquery.com/error/. – Tapas Bose Jul 13 '13 at 20:07
  • Would this work for class selector? Like `.images`? – Doug Molineux Sep 03 '13 at 16:29
  • 5
    Unfortunately, `.load` in this context has been deprecated since jQuery 1.8. For more recent version of jQuerys, use `.on('load', function(){ /* blah */ });` instead. – Fluoxetine Jun 19 '14 at 16:38
  • Sarfraz, you can update your answer with @Fluoxetine 's comment. So it can still be a great answer – rpax Aug 04 '14 at 16:57
  • how do achieve the same with multiple images? – pavitran Mar 29 '17 at 06:17
11

I use a similar technique to what @Sarfraz posted, except instead of hiding elements, I just manipulate the class of the image that I'm loading.

<style type="text/css">
.loading { background-image: url(loading.gif); }
.loaderror { background-image: url(loaderror.gif); }
</style>
...
<img id="image" class="loading" />
...
<script type="text/javascript">
    var img = new Image();
    img.onload = function() {
        i = document.getElementById('image');
        i.removeAttribute('class');
        i.src = img.src;
    };
    img.onerror = function() {
        document.getElementById('image').setAttribute('class', 'loaderror');
    };
    img.src = 'http://path/to/image.png';
</script>

In my case, sometimes images don't load, so I handle the onerror event to change the image class so it displays an error background image (rather than the browser's broken image icon).

Seth
  • 45,033
  • 10
  • 85
  • 120
  • This is different - you're loading the image _outside_ the page DOM then moving it onto the `img` element from the browser cache. The method might not work if the image has some sort of _no caching_ HTTP response header. – Edward Aug 12 '17 at 17:21
3

Instead of just doing this quoted method from https://stackoverflow.com/a/4635440/3787376,

You can do something like this:

// show loading image
$('#loader_img').show();

// main image loaded ?
$('#main_img').on('load', function(){
  // hide/remove the loading image
  $('#loader_img').hide();
});

You assign load event to the image which fires when image has finished loading. Before that, you can show your loader image.

you can use a different jQuery function to make the loading image fade away, then be hidden:

// Show the loading image.
$('#loader_img').show();

// When main image loads:
$('#main_img').on('load', function(){
  // Fade out and hide the loading image.
  $('#loader_img').fadeOut(100); // Time in milliseconds.
});

"Once the opacity reaches 0, the display style property is set to none." http://api.jquery.com/fadeOut/

Or you could not use the jQuery library because there are already simple cross-browser JavaScript methods.

Edward
  • 1,062
  • 1
  • 17
  • 39
0

Use a javascript constructor with a callback that fires when the image has finished loading in the background. Just used it and works great for me cross-browser. Here's the thread with the answer.

Community
  • 1
  • 1
bentedder
  • 796
  • 6
  • 21