4

I am trying to optimize a site which loads terribly. I already reordered, compressed and minified js and css, but the biggest problem are the images. This site has some really heavy images in it, so when it starts to load the content jumps while all the images are being loaded.

I cant manually set the height of the divs containing the images because they are user submitted, and although the width is a fixed value, height isn't.

I understand that this is probably not a good practice, but I think its better that the page takes two seconds before showing contents, that it being jumpy and unusable for those two seconds.

1.) Is this technically possible? How? (I would like to know this, even if its not a good practice)

2.) If this is not a good practice, how would you avoid this problem?

agente_secreto
  • 7,959
  • 16
  • 57
  • 83
  • 1
    Not really a best practice. Maybe try a pre-loader, or wait until all the images are loaded and then display them so that you have one jump instead of multiple. – ayyp Aug 11 '11 at 15:40
  • 1
    Even if the images are user submitted, you should still know what the dimensions are on the server side. Make sure you set width and height on your img tags. When rendering the HTML for the image tag, use a function that reads images and gives you properties. You could cache the dimensions somewhere – Ruan Mendes Aug 11 '11 at 15:49

5 Answers5

2

It's extremely easy with JQuery. I'd recommend using that framework anyway, even if it wasn't for this particular solution:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(){
        $('<img/>')[0].src = this;
    });
}

Use it like this:

preload([
    'img/apple.jpg',
    'img/banana.jpg',
    'img/pear.jpg'
]);

Hiding your site at this point is easy with CSS and JQuery:

CSS:

body {
    display:none;
}

JQuery:

$(function(){
    $('body').show();
    // or fade it in: $('body').fadeIn();
});
AlienWebguy
  • 76,997
  • 17
  • 122
  • 145
  • i think preloading wont solve this problem, since the images are to be displayed simultaneously, and the guy's problem is that they take time to load, this javascript will anyways load the images AFTER the body has loaded, so it doesn't hides the Absence of images until they are not loaded. – Pheonix Aug 11 '11 at 15:43
  • That looks nice @AlienWebGuy, but I dont really get what it's doing. I dont get what are you doing to the src value in the preload function, and on what event do you show the body. Would you mind explaining? – agente_secreto Aug 11 '11 at 16:09
  • Basically the code loops through all the images you want to preload and adds them to the DOM (not in any actual place on the screen, just the model itself). Then `$(function(){...` fires which is shorthand for `$(document).ready(function(){` – AlienWebguy Aug 11 '11 at 17:32
  • With CSS you set the body to `display:none` which hides everything - Then, when the DOM is ready and loaded, you show the body contents – AlienWebguy Aug 11 '11 at 18:09
  • This looks good but what do you do when you do not know what images will be on the page? E.g a client makes a page with a bunch of images on it – Chris G-Jones Sep 12 '13 at 03:31
1

Just after the Body tag, add a Div Element to cover the whole length and breadth of the page, make it white background or add a "Loading" image, set its z-index to Max (9999 or something) so its on top of everything, and give it some ID/Name

and Use a Javascript with Body onLoad Event to hide or remove that Div Element.

Something like

<body onload='document.body.removeChild(document.getElementById("bigDiv"));'>

<div style="width:100%;height:100%;background:white;" id=bigDiv>Loading...</div>
Pheonix
  • 6,049
  • 6
  • 30
  • 48
  • Does the onLoad event detect when the images are fully loaded? Or only the html document? – agente_secreto Aug 11 '11 at 15:55
  • Well i actually did this for my site which had a very long form (40 fields, and loads or Extras), but i suppose it will detect images too, just give it a try. :) – Pheonix Aug 11 '11 at 16:16
1

First important thing to check - make sure the images are cacheable. Sometimes caching of images is disabled. The way to check this is a direct call to the webserver:

 telnet localhost 8080
 GET /images/flibble.gif HTTP/1.0

And see what is returned. It should return something like Expires: or Cache-Control.

This page seems to describe it well: http://www.web-caching.com/mnot_tutorial/how.html

The other trick is to specify the size of the images in the tag. This vastly improves performance because the browser doesn't need to wait until the page is loaded.

cs94njw
  • 535
  • 5
  • 12
  • Interesting, they aren't... But this wouldnt solve the problem for first time visitors, right? – agente_secreto Aug 11 '11 at 15:56
  • Very very true. Personally, I expect pages to load slowly when I visit a new website, but if that's not acceptable then you need another solution. – cs94njw Aug 11 '11 at 15:59
1

I've written my own js image preloader before, what I'm about to post is pseudo-similar to it but will need some work. Basically in order to make your page load nicely, the answer isn't to hide the body to stop it jumping around, rather beautify what happens when the images do load. Besides throwing out the baby with the bath water, generally sites appear to the user to load faster if they can see something happening while they wait.

So what you need to do (for each image, or atleast each major or large image) is display a loading gif (check out http://ajaxload.info) while the image loads, then when it is finished you can use jQuery to animate it's container to the correct height and fade in the image. This stops your page jumping around (or rather makes it look prettier while it jumps).

To acheive this effect, something like this should do the trick:

function imageLoader(elem)
{
  //set all images in this elem to opacity 0
  elem.children('img').css('opacity', '0');
  var image = new Image();
  //show loading image
  elem.append('html for loading image');

  //when the image loads, animate the height of the elem and fade in image
  image.onload=function()
  { 
       var h = image.height;
       elem.animate({height:h+'px'}, function(){
         elem.children('img').fadeIn();
         elem.children('html for loading image').remove(); 
       });
  };

  image.src=elem.children('img').attr('src');
}

Use it like this:

imageLoader($('someElementWithAnImageTagInside'));

Again this is just psuedocode really but hopefully should give you some ideas.

Hope this helps

totallyNotLizards
  • 8,489
  • 9
  • 51
  • 85
  • Hmm that is a nice solution, but I dont think it would play very well with this site. This happens witjhquite a few images, so seeing three or four spinning wheels at the same time wouldnt look that great – agente_secreto Aug 11 '11 at 16:03
0

U can use block plugin to block the page. Link

kritya
  • 3,312
  • 7
  • 43
  • 60