9

There's tons of articles of how to preload an image, however I can't seem to find anything useful about preloading a background image with jquery.

I made a simple html mockup of what I'd like to achieve: http://jsfiddle.net/3rfhr/

  • A loading div appears
  • Background is loaded
  • Loading div disappears
  • Background DIV appear

I can handle the div transitions but I'm clueless as to how I should go about preloading a css background. Thanks for reading my question :)

Michael A
  • 9,480
  • 22
  • 70
  • 114
pufAmuf
  • 7,415
  • 14
  • 62
  • 95

5 Answers5

7

You can't as long as it's a background image. Load it normally and then set the background image. Something like this:

var $img = $( '<img src="' + src + '">' );
$img.bind( 'load', function(){
    $( '.yourDiv' ).css( 'background-image', 'url(' + src + ')' );
} );
if( $img[0].width ){ $img.trigger( 'load' ); }

the last line is needed in some browser in case the image is cached.

  • Aha, and so the `src` part is repaced by the url of the image? – pufAmuf Dec 27 '11 at 17:21
  • yes, `src` is the image url, set it to whatever you need. Chris Kempen's answer has a good idea in that he's grabbing the src from the CSS, though I'm not sure what the 2nd line is for –  Dec 27 '11 at 17:23
  • 1
    Can't is a strong word. You can load the image using the File Api and set the src attribute to "data:image/gif;base64,...my...encoded...image" See my post below for a reference to another post covering this technique. – Mike Gwilt Dec 27 '11 at 17:29
  • Hmm, maybe I did something wrong? http://jsfiddle.net/Zf7Jm/1/ `missing ) after argument list` – pufAmuf Dec 27 '11 at 17:30
  • @mgwilt -- um, you still "can't" :) Loading it as base-64 data has nothing to do with the fact that you ___can't___ catch the load event on the background image as long as it's in CSS. If you didn't notice, you aren't catching the CSS background-image load either :) –  Dec 27 '11 at 17:31
  • But you *do* have a callback on getting the base64 encoded version of the image from jQuery. You could preload all the images you like using that method and just set the css or src attribute whenever you want. Think of it in the other direction.. jQuery -> CSS not CSS -> jQuery ;D – Mike Gwilt Dec 27 '11 at 17:34
  • yeah, but that's entirely different than saying that my statement that "you can't as long as it's a background image" is incorrect! :) –  Dec 27 '11 at 17:35
  • @pufAmuf -- http://jsfiddle.net/Zf7Jm/2/ A few JS issues. Also, src has to be `url( ... )`, which I overlooked. –  Dec 27 '11 at 17:37
  • Sorry for the delayed comment, but this solution looks cool. Would that be a 'jQuery-ified' version of image preloading? If so, I think I'm going to use that from now on... :) – Chris Kempen Dec 27 '11 at 17:54
  • 1
    @ChrisKempen -- You could easily make that a jQuery plugin by wrapping most of the code with `$.fn.preloadImage = function(){ return this.each( function(){ ........ } ); }` and replacing the load function with something like `$self.trigger( 'loaded' )` -- note that you should also prevent double-calling of the function in this case (the last line will sometimes double-call the callback, but it wasn't important in this case so I ignored it) –  Dec 27 '11 at 17:56
4

To do the preloading, why not grab the URL from the css attribute with jQuery? Something like this:

var bg_url = jQuery("#DIV-THAT-NEEDS-PRELOADING").css('background-image');

// using regex to replace the " url( ... ) "...
// apologies for my noobish regex skills...
bg_url = str.replace(/ /g, '', bg_url); // whitespace...
bg_url = str.replace(/url\(["']?/g, '', bg_url); // next, the 'url("'...
bg_url = str.replace(/["']?\)/g, '', bg_url); // finally, the trailing '")'...

// without regex, using substring if confident about no quotes / whitespace...
bg_url = bg_url.substring(4, bg_url.length-1);

// preloading...
var img = new Image();
img.onload = function()
{
    // do transitions here...
};
img.src = bg_url;
Chris Kempen
  • 9,491
  • 5
  • 40
  • 52
  • 2nd line should probably be a regex, unless you're positive that whitespace is ignored in all browsers? (took me a minute to realize that it's to parse `url( ... )`) –  Dec 27 '11 at 17:24
  • To strip the `url( ... )` from the css attribute. Yep, could definitely use regex, and as far as I know jQuery should always give you a nice string value ;) – Chris Kempen Dec 27 '11 at 17:27
  • Yeah, realized that :) Edited my previous comment right when you answered, concerned about whitespace and/or quotes though. –  Dec 27 '11 at 17:29
  • Hi Chris, this looks great! Though, sorry if this looks stupid, but can you please point me to what I did wrong here? http://jsfiddle.net/Zf7Jm/3/ – pufAmuf Dec 27 '11 at 17:41
  • Give your `div` a specific `width` and `height` in the CSS, like `500px` for both width and height, and that should do the trick :) – Chris Kempen Dec 27 '11 at 17:45
2

Here's a post from last week that covered preloading images with jQuery: HTML 5 File load image as background-image

And here is the solution that post referenced: http://sveinbjorn.org/dataurls_css

Community
  • 1
  • 1
Mike Gwilt
  • 2,399
  • 1
  • 16
  • 14
  • This might be the only solution using the HTML 5 API, but with regular image loading using URLs this solution was slower than the solution of @cwolves. The images load more slowly and debugging is also slower because the debugger displays the large base64-encoded image data. – jbustamovej Jul 19 '13 at 16:38
1

You logic is almost good, but you can not catch events for CSS in jquery.

You need to load the background image to some <img> element. Catch the event load of that element and when it's fired you change the background image to that src and do the rest of your logic.

Bruno Costa
  • 2,708
  • 2
  • 17
  • 25
0

A working example with a mock setTimeout to simulate loading time.

The relevant jQuery code is:

$('#LOADING-SIGN-DIV').fadeOut();
$('#DIV-THAT-NEEDS-PRELOADING').fadeIn();
Josh Smith
  • 14,674
  • 18
  • 72
  • 118