24

I have a sidebar widget that has an image background.

Over this is a search input form. I don't want the input to show before the image has loaded.

Is there a way to attach an load event handler to CSS background images like normal img elements/objects?

I know this could be done on a normal image, but I'd like to keep it as a CSS background because the image is part of a sprite. I am using jQuery, so solutions using jQuery or plain DOM JS are equally good.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Cole
  • 1,483
  • 1
  • 11
  • 20

4 Answers4

26

You could load the same image using the DOM / a hidden image and bind to the load event on that. The browser's caching should take care of not loading the image twice, and if the image is already loaded the event should fire immediately... not tested, tough.

Félix Saparelli
  • 8,424
  • 6
  • 52
  • 67
  • And here's how to do it: http://stackoverflow.com/a/5058336/3062017 – Luca Steeb Jan 08 '16 at 23:08
  • In the future a more advanced, predictable, and possibly more efficient method for detecting whether assets referenced in CSS (images, fonts...) have loaded will be to use [ServiceWorkers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) and [postMessage](http://www.w3.org/TR/service-workers/#service-worker-postmessage): the Service Worker would load the asset, pass it to the page, and post a message to indicate the asset has loaded, in a way that is actionable from within JS, without relying on the browser's own caching to avoid an extra request. – Félix Saparelli Jan 10 '16 at 01:35
7

In chrome, using .ready() of jQuery seems to work for me. Here's my fiddle:

http://jsfiddle.net/pWjBM/5/

The image is just a random one I selected that is reasonably large - it actually takes a very long time to load in some of my tests, so may be worth replacing with something a bit smaller. But the end result is what you want I think: It takes a while to load, and once it's loaded the alert and then textbox (#txt) displays. Seems to work in Firefox too; not sure about other browsers.

EDIT: Hah, it seems to work in Chrome, Firefox and Safari. Doesn't work in IE8. So... it works in all real browsers :)

EDIT2: After much fiddling, a combination of Allesandro and my own solution seems to work. I use .ready() on a hidden img to detect when the image is actually loaded, then load it into CSS background.

http://jsfiddle.net/pWjBM/41/

HTML:

<div id="testdiv">
    <input type="text" id="txt" style="display:none;" />
</div>
<img src="http://www.nasa.gov/sites/default/files/images/712130main_8246931247_e60f3c09fb_o.jpg" id="dummy" style="display:none;" alt="" />

Javascript:

$(function() {
    $('#dummy').ready(function() { 
        alert('loaded');
        $('#testdiv').css('background-image', 'url(http://www.nasa.gov/sites/default/files/images/712130main_8246931247_e60f3c09fb_o.jpg)');
        $('#txt').show(1000);
    });
 });

CSS:

#testdiv {
    background:#aaaaaa none no-repeat right top;
    width: 400px;
    height: 400px;
}

#txt{
    margin-left: 180px;
    margin-top: 140px;
}

NOTE: There is a comment below about this not working because you can change the url of the image and it still fires the loaded event. This is in fact working pretty much exactly as I'd expect given the current code - it doesn't check if the url you're pointing to for your "image" is valid and really an image, all it does is fires an event when the img is ready and change the background. The assumption in the code is that your url points to a valid image, and I think any further error checking is not really needed given the question.

mutex
  • 7,536
  • 8
  • 45
  • 66
3

You can try this, it's pretty basic.

function onImageLoaded(url, callback) {
    const img = new Image();
    img.src = url;
    img.onloadend = callback;   //Image has loaded or failed
    return;
}

It will work for background images and img tags.

Ric Flair
  • 387
  • 3
  • 5
2

do not set background in css, but load the image into an img tag created with javascript (or better, jquery). once loaded, it will fire the load event. when this event is fired, apply the style property to your div

Alessandro Pezzato
  • 8,603
  • 5
  • 45
  • 63
  • I've been trying this approach to get around IE8s lack of a "DOMContentLoaded" event which appears to be why .ready() doesn't work with <= IE8... however it doesn't seem to work either. See the jquery documentation for .load() at http://api.jquery.com/load-event/ under "Caveats of the load event when used with images" – mutex Jun 09 '11 at 00:32
  • Do not set background in css? Listen. I use css background image so i can use the "cover" option. This is not possible with image tag unless you use a library which I dont think there is any as of writing this. – Mustafa Nov 03 '17 at 22:54
  • When Style applied , it will take image from cache. Nice Idea. – Senthil Kumaran C May 15 '21 at 04:18