Christian Heilmann

Author Archive

Thinking lowsrc Γ’β‚¬β€œ how to make sites appear to be available a lot faster

Monday, July 9th, 2007

*ZOMG Update!*: We put our heads together and came up with a client side solution without a PHP component that does the same as this one explained in detail here.

Those of you who’ve been around some years may remember an otherwise forgotten non-standardized HTML attribute called lowsrc. It was supported by Netscape browsers and allowed you to define a black and white preview picture of the real picture. The browser would load the “diet” black and white shot first and then load the “full fat” colour shot and overlay the preview picture line by line. Alongside progressive JPGs (which load in lower quality first and then progressively get clearer) and interlaced GIFs (which loaded every second line first and then subsequently filled up the rest) this was a killer trick to speed up your web site in the times when 56K Modems were luxury items.

How come that we have fast connections but sites are still slow?

Most of us are on faster connections these days and yet we constantly get annoyed at how long it takes for some pages to finish loading. The reason is that we embed too many resources (videos, images, scripts) in the page.

Browsers in general seem to download two resources in parallel and stall the rest of the dependencies from loading until these are done. When you use a lot of images, especially from different servers this leads to a long delay, as for each of these images the browser needs to initiate an HTTP request, convert the URL to a DNS and IP and pull the image.

Furthermore the browser shows us an endless spinning wheel or progress bar and informs us that “10 of 73 resources” have been loaded. While this does not necessarily mean that we cannot use the current document (browsers these days at least don’t stop rendering halfway through – unless you use inline scripting that fails) it still gives us an impression that things still happen and the document is not ready for us yet.

The most common example where this happens is when you use avatars on your site – the small images depicting the user that contributed the content adjacent to it. Using a lot of these can make the page appear very slow, as the following example which loads and display fifty results from Yahoo! Answers with avatars shows.

  • Load fifty answers with avatars (opens in a new window) avatars.php

During testing on this connection using Firebug’s network monitor this loaded 30 resources with 125kb in overall 14.92 seconds.

This delay also means that scripts that get fired via the onload handler of the window will get delayed until all the images were loaded, which is why libraries have to use methods like onAvailable , onDOMReady or onContentReady to run our scripts.

However, if you are in control of the middle tier of your server than there is a solution to make this delay less painful for the end user and seemingly deliver your pages quicker.

  • Load fifty answers with avatars delayed (opens in a new window) avatarsdelay.php

During testing on this connection using Firebug’s network monitor this loaded 30 resources with 125kb in overall 12.7 seconds, however the wheel of the browser stopped spinning after 3 seconds and I got the impression all is done. What was the difference?

The avatars.php example uses CURL and PHP to load information from the Yahoo! Answers API. We serialize the return value and spit out the HTML:

$p){
echo '
'.$p['UserNick'].''; echo '

'.$p['Subject'].'

'; echo '

'.$p['Content'].'

'; } ?>

This results in all of the HTTP requests that delay the user-felt availability of the site. A simple trick and small change to the script makes this delay obsolete.

Shifting the HTTP overhead further down the timeline

Using JavaScript we have the option to delay the loading of extra content that is “not really needed” for the enjoyment and availability of your site. As the avatars are not really necessary to get the gist of the answers page, we can alter the backend script to harvest the image URLs and replace all the images with different URLs with a placeholder – say a “grey man” picture. In order to allow us to identify the pictures later and link them to the harvested URL, we add a dynamic ID.

$p){
echo '
id="i-'.$key.'" src="http://us.i1.yimg.com/us.yimg.com/i/us/sch/gr2/nophoto3_48x48.gif" width="48" height="48" alt="'.$p[UserNick].'">'; echo '

'.$p['Subject'].'

'; echo '

'.$p['Content'].'

'; $out[$key]='''.$p['UserPhotoURL'].'''; } ?>

When the page and all the other assets have finished loading we load the rest of the pictures by replacing the src attribute of all the placeholders with the real URLs. This script should go to the end of the document.

Yes, this makes your avatars dependent on JavaScript, but it has no real impact on accessibility or SEO as the alternative text of each avatar is still available. The only impact it has is that visitors will see a transition from a “grey man” to the user’s avatar and as most of the time avatars are outside the initial viewport or at its boundaries the majority of users won’t be the wiser about our little trick – but they get page that seems to have loaded a lot faster.

Delaying the delivery of heavy screen furniture

While this trick is most efficient with third party images, we could also go further in our optimization and take another leaf out of the book of tricks of the days of slow connections.

When Netscape 4 and other older browsers still made up a substantial part of the overall visitor numbers, the main trick to cater for these browsers and newer ones was to use the @import directive to add a style sheet for newer browsers and have a simple LINK to add the one for these oldies:


(The single quotes also blocked out MSIE 5/Mac)

We can do something like that easily for the document, too. Simply create a more basic style sheet that for example uses background-colours instead of fancy gradients, massive bevels or pretty but very large nature shots. Then create an extra style sheet that adds all of these background-images. As URLs in CSS are as much an HTTP request as embedded images are, this’ll give us the same gain. In the document’s onload handler, all you’ll need to do is create a new LINK element pointing to the style sheet with the images and add it to the head of the document.


[...]

This’ll add all the fancy imagery after the main document was loaded and replace background colours that did the job until the page was ready and we can go and make it prettier.

[tags]optimization,speed,avatars,php,javascript,faster pages,webdevtrick[/tags]

In need of a new title

Tuesday, July 3rd, 2007

Just like the Childlike Empress in the Never Ending Story I am right now without a proper name for my new role.

Yes, that is right, I slipped into a new role in my current job and boy is it something I wanted to do for years and years. However, the dilemma I am in is that the job is so versatile and multi-facetted that I have trouble coming up with a proper job title! This is where you come in. Can you think of a good job title that explains my following responsibilities?

Responsible for the following key areas related to Code Quality, Code Reuse, Talent Acquisition and Talent Development.

  • Internal training and code review in key technologies and development standards.
  • External evangelism and assessment of these technologies through the engagement of developer communities.
  • Supporting internal teams in identifying, assessing and hiring new talent.
  • Developing new tools that will support development standards to help us build better products faster.
  • Build and maintain front-end code libraries for reuse

Any ideas?

[tags]whatsinaname,title,jobtitles,developer,webdevelopment[/tags]

Collapse Flickr comments – My first greasemonkey script

Friday, June 29th, 2007

I couldn’t sleep because of this bloody cold and thought I give Greasemonkey a go. One of my biggest annoyances in flickr is that when you comment on some very popular photo (normally containing a pretty lady and some nudity) you have to scroll through dozens of long comments in order to reach the next photo and comments. This gets exceedingly annoying when people think it is needed to have images depicting “flickr awards” that are as big as they are ugly.

Anyways, the script collapses all the comments and adds “+” links that allow you to show and hide the list of comments for each photo.

Greasemonkey script to collapse comments

Hope it is helpful, my flickr experience became a lot less aggravating :)

[tags]greasemonkey,script,hack,flickr,comments,collapsing,interface,flickrhack[/tags]

Shortening JavaScripts with Math

Thursday, June 28th, 2007

I just went through an exercise for a DOM scripting course with the YUI and had the task to write a function that takes any element and centers it at the current cursor position. I also wanted to make sure that the displayed object never causes scrollbars or gets cut off when the cursor is too high up the document.

Getting the size of the object and the browser constraints was easy with the YUI. I sent the object as o and e is the event:

var size = YAHOO.util.Dom.getRegion(o);
var oHeight = size.bottom - size.top;
var oWidth = size.right - size.left;
var screen = [YAHOO.util.Dom.getViewportWidth(), YAHOO.util.Dom.getViewportHeight()];
var curpos = [YAHOO.util.Event.getPageX(e), YAHOO.util.Event.getPageY(e)]

Now I had the problem of keeping the values in the constrains. Centering the element was easy, you just substract half of the height from the vertical position and half of the width from the vertical cursor position.

var x = curpos[0]- oWidth/2;
var y = curpos[1]- oHeight/2;

I then had to compare both with their constraints and set them to the appropriate values, which was a lot of if statements:

if(x < 0){
x =0;
}
if(x + oWidth > screen[0]){
x = screen[0] - oWidth;
}
if(y < 0){
y =0;
}
if(y + oHeight > screen[1]){
y = screen[1] - oHeight;
}
clunky, and I shortened it using the ternary notation:
var x = curpos[0] - oWidth/2;
x = x < 0 ? 0 : x;
x = x + oWidth > screen[0] ? screen[0]-oWidth : x;

var y = curpos[1] - oHeight/2;
y = y < 0 ? 0 : y;
y = y + oHeight > screen[1] ? screen[1]-oHeight : y;

lt felt terrible. I then remembered the Math object in JavaScript and that it has two methods that are terribly useful in this case: min() and max(). Both return a value that is either the smaller or the larger value, which means you can use it to constrain a value to a certain range. Using Math, the whole logic can be done in two lines of code:

var x = Math.min(Math.max(curpos[0] - oWidth/2, 0), screen[0] - oWidth);
var y = Math.min(Math.max(curpos[1] - oHeight/2 ,0), screen[1] - oHeight);

That is not the end of it, though. If you know that you should get back a number, you can use max() to normalize browser differences, like the Dom utility of the YUI does:

var scrollTop=Math.max(doc.documentElement.scrollTop,doc.body.scrollTop);

This works around the MSIE issue of reporting different values for scrollTop depending on which rendering mode you are in.

[tags]webdevtrick,javascript,math,comparisons,beginningjavascript[/tags]

DOM JavaScript Cheat Sheet

Wednesday, June 27th, 2007

I’ve just put together a small DOM cheatsheet for some developers here and thought why not share it and CC it in case it can be handy for you, too:

DOM JavaScript Cheatsheet

Click the screenshot or download the PDF version of the cheat sheet (85KB) here.

[tags]DOM,JavaScript,helper,PDF,cheatsheet,Creative Commons[/tags]