1

I need to understand how image preloading works in browsers. Lets say I have this piece of code:

<script type="text/javascript" language="JavaScript">
    companyLogo = new Image();
    companyLogo.src = "/images/image1.jpg"
</script>

then somewhere below my page i have following.

<img src= "/images/image1.jpg" /> 

now as you can see, first i preloaded the image /images/image1.jpg And then i am using it within my image tag.

my website has product images, which are very HD and my entire page sometimes hangs while main image is loading. i dont mind size being big for my images, what I want to do is....keep loading the page with content & other elements and show the image as soon as its loaded (however do not HANG/PAUSE the page just because image is not loaded yet).

Now the above approach, what does it exactally do? does it preload the image in cache and waits and hangs the page? or it does exactally what i am trying to do?

Thanks

highwingers
  • 1,649
  • 4
  • 21
  • 39
  • 2
    Why are you delivering HD images? For download? If your page is hanging because of it it's not a pre-loader you want is a post-loader. – Popnoodles Jan 17 '13 at 23:17
  • 2
    I'm thinking you should look more into image optimization first, then preloading. Preloading won't help you a whole lot if your images are still taking seconds to load. – Samsquanch Jan 17 '13 at 23:18
  • Lets not stick to HD image and optimization arguments...please i need explaination. this question is more educational then applying best practice. – highwingers Jan 17 '13 at 23:21

3 Answers3

4

While it sounds like you should be optimising your images instead, I;m happy to show you how I would do it.

Don't include the image src, hide it in data. (Use correct width and height so your page doesn't jump when they eventually load.)

<img src="1px.gif" data-src="http://the.real.src" class="justyouwait" style="width:10000000px; height:1000000px;" />

Then on dom ready, i.e. when your page has loaded, load them

$(function(){
    $('img.justyouwait').each(function(){
        $(this).attr('src', $(this).data('src'));
    });
});

Or add a bit of niceness

$('img.justyouwait').each(function(){
    $(this).css({opacity:0}).load(function(){
        $(this).animate({opacity:1},1000); // fade them in
    }).attr('src', $(this).data('src'));
});
Popnoodles
  • 28,090
  • 2
  • 45
  • 53
2

I would do it on DOMReady. But it essentially attempts to load the file at the same time the page is loading, there should be no hanging. However it will not "lazy" load the image. Usually this technique is used to load images that MAY be required. I would load a low res first, in the HTML, and via javascript update the images once the high res images are ready. Or better yet, simply load a Web safe image and give users a link to the high res if they want it.

Bad idea to force people to download high-res images. That's a good way to have people avoid your site.

EDIT:

So you could do something like:

<img src="src/to/placeholder.jpg" data-path="path/to/high/res.jpg" class="lazyload"/>

Then have a javascript function do:

$('.lazyload').each(function(){
    $(this).attr('src',$(this).data('path'));
});

Not sure if my code is exact, but you get the point.

EDIT: When the DOM is loading you are essentially loading the same placeholder image for all of your product images. In the background, javascript requests the real image based on the path in data-path. Then when the image is done loading, the placeholder source gets updated with a nicer image. Add some fade or whatever if you like.

Leeish
  • 5,203
  • 2
  • 17
  • 45
  • My goal here is to....load the page content & dont hang the page because of image size. so whats the best practice? – highwingers Jan 17 '13 at 23:22
  • I think then you want to load no image. Load them via javascript, and then replace the source via javascript. Though I would really suggest at least loading a placeholder or low res version. You can create an image placeholder for all of them while they are loading. – Leeish Jan 17 '13 at 23:23
  • ahaan, this is starting to maike sense. so why do people use the approach which I have posted in my question, what is that for? and do you have any online example for me to read? Thanks – highwingers Jan 17 '13 at 23:26
  • Lets say you have an image that when you hover, changes to another image. If you don't preload there will be a slight delay from the hover to when the image appears. Exmaple, old website I made: http://crowtint.com/ Hover over the social icons. A sprite works better in that instance, but I was young and reckless. – Leeish Jan 17 '13 at 23:28
  • Please use .data('src') not attr('data-src'). Data is loaded into DOM on page load. Once there it can be manipulated. You can't access data you add using .data() via attr() because adding data doesn't manipulate the html like attr() would. It doesn't involve re-writing HTML on the fly so is a lot faster. – Popnoodles Jan 17 '13 at 23:31
  • I saw your code and didn't use that before. It's good to know that the data is accessible that way. I never looked it up and just assumed data-whatever was a custom attribute. – Leeish Jan 17 '13 at 23:33
  • I've seen that a few times. One kitten dies every time it happens. :( +1 for saving kittens – Popnoodles Jan 17 '13 at 23:34
  • so hold a sec, this trick basicly is loading a placeholder using a "src" attribute, then we have a custom attribute "data-src" which holds the actuall path to the HD image, but then in jQuery you are accessing the actuall image path by using $(this).data('src'), what is data? and what happened to data-src attribute? – highwingers Jan 17 '13 at 23:37
  • @popnoodles corrected me. I was unaware that `data-` actually loaded the data to the dom. You could to `rel="path/to/file` or `poop="path/to/file"` if you want and access that via `$(this).attr('poop')` but data has the added function of then being avaialable via `$(this).data('src')`. Where src is the value of `data-src` not the image src. I'll edit with different names. – Leeish Jan 17 '13 at 23:40
  • and it has no browser compatiablity issues? – highwingers Jan 17 '13 at 23:42
  • http://ejohn.org/blog/html-5-data-attributes/ http://stackoverflow.com/questions/2412947/do-html5-custom-data-attributes-work-in-ie-6 – Leeish Jan 17 '13 at 23:43
  • good you mentioned, i have not switched to HTML5, i need a standrd HTML 4 solution. – highwingers Jan 17 '13 at 23:46
  • Does not need to be HTML5, jQuery deals with it. Hang on, two people independently post virtually exactly the same solution and half an hour later you still haven't tried it? – Popnoodles Jan 17 '13 at 23:46
  • But without jQuery it's useless no? – Leeish Jan 17 '13 at 23:47
  • lol, i am very picky...i was reading on what exactally "data" attribute is before I try it:) – highwingers Jan 17 '13 at 23:48
  • I'm asking, because I don't know. – Leeish Jan 17 '13 at 23:50
0

I wrote this simple jQuery plugin to help with this.

imgur.js

/*
    Plugin: IMGUR
    Author: Drew Dahlman ( www.drewdahlman.com )
    Version: 0.0.2
*/

    (function($) {

        $.fn.imgur = function(options,loaded) {
            var defaults = {
                img: '',
            }

            if(loaded){
                var callback = {
                    loaded: loaded
                }
            }

            return this.each(function() {

                var settings = $.extend(defaults,options);
                var callbacks = $.extend(callback,loaded);
                var _image;

                var $this = $(this);

                function init(){
                    if(callbacks.loaded != null){
                        _image = new Image();
                        _image.onLoad = loaded();
                        _image.src = settings.img;
                    }
                }
                function loaded(){
                    if(callbacks.loaded != null){
                        callbacks.loaded($this,settings.img);
                    }
                }
                init();
        });
        };

    })(jQuery);

How to use

in your html assign a class if you have multiple images to load.

<img src='' data-image='images/image1.jpg' class='preload'/>

Then in your javascript call ( this assumes you're using jQuery )

<script>
$(".preload").each(function(){
 var $this = $(this);
 $this.imgur({
  img: $this.data('image') // in your case
 },function(el,data){
   el.attr('src',data);
 });
});
</script>

This will use the data-image to load the image then when it's loaded it will add that data to your element that you've supplied it with.

cheers!

Drew Dahlman
  • 4,952
  • 1
  • 22
  • 34
  • Can you explain what your plugin does, when without it, the short few lines of jQuery will cope perfectly well? – Popnoodles Jan 17 '13 at 23:49
  • Basically it loops through your elements with a specific class and loads the images - once the image has loaded it fires a callback that sets the image source to your image. The browser caches the data so when it adds it as the source it uses the browser cache and loads quickly. It also helps by putting the images into a queue. – Drew Dahlman Jan 17 '13 at 23:52