2

I am having troubles making a working preloader for css background images. Here is the situation: I have several hidden elements, each one has a css background image.

When the user clicks on a "start" button, I then use jquery to show the elements (one after an other: as one is shown, the other is hidden). However, the "start" button should be available only after all the images are loaded.

I am using this preloader:

function preloadimages(arr) {
    var newimages=[], loadedimages=0
    var postaction=function(){}
    var arr=(typeof arr!="object")? [arr] : arr

    function imageloadpost() {
        loadedimages++
        if (loadedimages == arr.length) {
            postaction(newimages) //call postaction and pass in newimages array as parameter
        }
    }

    for (var i=0; i<arr.length; i++) {
        newimages[i] = new Image()
        newimages[i].src = arr[i]
        newimages[i].onload = function() {
            imageloadpost()
        }

        newimages[i].onerror = function() {
             imageloadpost()
        }
    }

    return { //return blank object with done() method
        done:function(f) {
            postaction = f || postaction //remember user defined callback functions to be called when images load
        }
    }
}

preloadimages('img01','img02','img03')
    .done(function(images) {
        alert(images.length + " images loaded"); 
    });

This, however, loads only 1 image.

I tried some other codes as well, with no results. Should image preloaders actually work on css background images? Or are they meant only for tags?

pbaris
  • 4,525
  • 5
  • 37
  • 61
DavidTonarini
  • 941
  • 3
  • 17
  • 35

2 Answers2

5

There's a really nice pure CSS solution for preloading background images that I think could help you. The concept behind it is to place the background images on a pseudo-element that is loaded when the page loads but is not shown. This causes the browser to load the images so that when they are called later by another element they are ready to go. Here's some sample code:

.main-element {
    background-image: url(your_url_here);
}
.main-element:after {
    display: none;
    content: url(your_url_here), url(another_url_here), url(another_url_here), etc.
}
.hidden-element {
    display: none;
    background-image: url(your_url_here);
}
.main-element:hover {
    .hidden-element: display: block;
}

Here's a link to an article with more info about this technique: http://www.thecssninja.com/css/even-better-image-preloading-with-css2

DMTintner
  • 14,405
  • 5
  • 35
  • 32
  • Seems nice, but I couldn't get it to work. Probably that's because I still need javascript/jquery to show the elements according to what user does? Anyway the image still loads only after the .show() is performed – DavidTonarini Feb 03 '13 at 13:39
  • thats totally fine it should still work and is unrelated to whatever method you use to show the elements. The images are actually being loaded on a completely separate element (the pseudo-element) anyway. I would just use jquery show() or jquery addClass() to provide a class to the element you want to show and then style it display: block; – DMTintner Feb 03 '13 at 14:49
0

I got it to work! This is a pretty simple jquery solution:

$(".hidden-element").show(); $(".hidden-element").hide();

This is not detected by the user, and still seems to force the browser to load the images I'm still unable to use callbacks after loading is done, but this work in ratice

DavidTonarini
  • 941
  • 3
  • 17
  • 35
  • This is a lot of unnecessary processing and not a very efficient way to handle this issue. You should aim to keep your code DRY, and since you are going to again have to call show() or toggle() on the elements you want to interact with you are repeating yourself here just to get the images to load. – DMTintner Feb 03 '13 at 14:53