user2700923
user2700923

Reputation:

Can I "pre-load" an image with JS to be used as a CSS background-image?

Can images be preemptively loaded into the page with javascript so that they can be used at any time as a CSS background image without any request/upload delay?

If so, how?

Upvotes: 0

Views: 376

Answers (5)

Phaedra
Phaedra

Reputation: 247

I don't think that using an hidden img tag is the correct way, i'd rather use an "new Img(url)" and attaching to it an onload event where you can set the image as background-image to the element you want.

img = new Image();
img.onload = function(){
  // set background-image
};
img.src = image_url;

be sure to put img.src after attaching onload, or you risk that the image is loaded before the event is attached.

Maybe a more complete base to build on:

function preload(list, callback, imageCallback, errorCallback) {
  if (typeof(list) === "undefined"
      || list.length === 0) {
    return;
  }
  var len = list.length;
  var timers = {};
  var checkLen0 = function() {
    if (len === 0) {
      if (typeof(callback) === "function") {
        callback();
      }
      delete(timers)
    }
  }
  var onload = function() {
    clearTimeout(timers[img]);
    if (typeof(imageCallback) === "function") {
      imageCallback.call(img);
    }
    len--;
    checkLen0();
  }
  var onerror = function() {
    clearTimeout(timers[img]);
    if (typeof(errorCallback) === "function") {
      errorCallback.call(img);
    }
    len--;
    checkLen0();
  }
  for (var i = 0; i < list.length; i++ ) {
    var img = new Image();
    img.onload = onload;
    timers[img] = window.setTimeout(5000, onerror);
    img.src = list[i];
  }
}

Upvotes: 3

Francisco Presencia
Francisco Presencia

Reputation: 8841

While SomeKittens answer is valid, it'll delay the page load as commented by Jimmy. If you are using jquery, I'd go with something like this instead to keep your style, structure and logic separated:

<style>
  .preload-img { display: none; }
</style>

...    

<div class = "preload-img">/path/to/image.jpg.png.gif.bmp</div>

...

<script>
$(document).ready(function(){
  $(".preload-img").each(function(){
    preloadImage = new Image();
    preloadImage.src = $(this).html();
    });
  });
</script>

Of course, from there on you can optimize/change it. The advantadge of this is that you can create the <div> dynamically with PHP and you can have all your javascript cached properly as a separated file.

Upvotes: 1

SomeKittens
SomeKittens

Reputation: 39522

You don't even need to use JS for this (with the downside of delaying the page load event). Include something like this:

<img src="/path/to/image.jpg.png.gif.bmp" style="display: none" />

This will trigger a request for the image, and add it to the local cache. When you set the CSS background-image property, the image will already be in the local cache, eliminating the delay of another request.

Alternatively, you can accomplish the same thing without delaying the page load by creating the images in JavaScript (this solution allows for multiple images):

function preload(list, callback, imageCallback) {
    var at, len;
    at = len = list.length;
    for (var i = 0; i < len; i++ ) {
        var img = new Image();
        img.onload = function() {
            if( imageCallback ) {
                imageCallback.call(this, this, len-at, len);
            }
            if( !--at ) {
                callback(list);
            }
        };
        img.src = list[i];
        list[i] = img;
    }
}

You'd call this with:

var list = preload(["1.png","2.png","3.png" ... ], function complete(list) {
   console.log('images all loaded!');
}, function loaded(image, index, listCount) {
   console.log('image ' + index + ' of + 'listCount + 'is loaded');
});

(Thanks to @rlemon for the preload code)

Upvotes: 3

Jimmy Breck-McKye
Jimmy Breck-McKye

Reputation: 3034

Just as a caveat to SomeKittens' answer above, a particularly large background image should probably be added as a hidden background / via JavaScript after page load, as content images delay the firing of window.onload and may therefore create the perception of a slow loading page.

Given that it sounds like you're using dynamic content anyway, this may be an acceptable solution. It also allows you to do preloading programmatically as required, which may be better for maintenance.

Upvotes: 0

mrserge
mrserge

Reputation: 199

There is an excellent framework for this job called Emerge.js http://ilyabirman.net/projects/emerge/

Quote from project page: Emerge.js is a framework for coordinated page loading. Normally, when a complex web page is loading, images appear in random order, causing unpleasant flashing. To replace it with nice and coordinated animations, programming is required. Emerge.js simplifies the task by removing the need to write any Javascript code. The framework uses a declarative approach, where you specify a desired behavior for each element and do not think about the implementation. Emerge.js uses jQuery.

Upvotes: 0

Related Questions