views:

302

answers:

2

I'm working on a jquery based homepage with 5 or so hidden divs, each containing several background css images.

The issue is that the browser doesn't load css images into the DOM until the visibility of the parent layer is shown, causing images to slowly load in when the layer becomes visible.

Solutions I've already considered:

  • CSS sprites (too much work to redesign for this, and wont really work when showing/hiding divs)
  • This jQuery plugin that auto-loads css background images (simply doesn't work for me as reported by many others).
  • preloading the images via js:

    $(function() { function preloadImg(image) { var img = new Image(); img.src = image; }

    preloadImg('/images/home/search_bg_selected.png'); });

    This solution seems to load the image into the dom twice...once when the js loads it, and then again when the div layer that loads it becomes visible...so it makes 2 http calls, thus not working

Any other solutions for this problem that I'm missing?

Thanks!

+5  A: 

When you said other ways do you mean ones that don't use Javascript?

<script language="JavaScript">
function preloader() 
{
     // counter
     var i = 0;

     // create object
     imageObj = new Image();

     // set image list
     images = new Array();
     images[0]="image1.jpg"
     images[1]="image2.jpg"
     images[2]="image3.jpg"
     images[3]="image4.jpg"

     // start preloading
     for(i=0; i<=3; i++) 
     {
          imageObj.src=images[i];
     }
} 
</script>

Other none JS ways are to place some html in your page somewhere so it's not seen:

<image src="picture.jpg" width="1" height="1" border="0">

or HTML...

<img src="images/arrow-down.png" class="hiddenPic" />

...and CSS...

.hiddenPic {
    height:1px;
    width:1px;
}

More JavaScript Methods:

function preload(images) {
    if (document.images) {
        var i = 0;
        var imageArray = new Array();
        imageArray = images.split(',');
        var imageObj = new Image();
        for(i=0; i<=imageArray.length-1; i++) {
            //document.write('<img src="' + imageArray[i] + '" />');// Write to page (uncomment to check images)
            imageObj.src=images[i];
        }
    }
}

Then load the images using something like:

<script type="text/javascript">
preload('image1.jpg,image2.jpg,image3.jpg');
</script>
Shadi Almosri
Thanks for all of the suggestions! I'll give em a try tomorrow and see what works. I did try the 1x1 div method but the rails app I'm working with assigns a caching hash to the end of the image url...so the browser treats them as different images as the ones in the css.
+1  A: 

"This solution seems to load the image into the dom twice...once when the js loads it, and then again when the div layer that loads it becomes visible...so it makes 2 http calls, thus not working"

The second http request should respond in a 304 (not modified), so I guess that's ok? Another options is to load the image via jQuery and then insert as background image inline via DOM, like:

jQuery.fn.insertPreload = function(src) {
    return this.each(function() {
        var $this = $(this);
        $(new Image()).load(function(e) {
            $this.css('backgroundImage','url('+src+')');
        }).attr('src',src);
    });
};

$('div').insertPreload('[huge image source]');
David