Camen Design

c share + remix

Website Optimisation Measures

  1. Move Scripts to the Bottom of the Body
    1. Use async and defer Script Attributes
  2. Ensure the Site Works With JavaScript Off
  3. Provide Proper Fallbacks for Flash Content
  4. Clean Up the Head
  5. Styleheets First
  6. Add Height & Width on <img> Tags
  7. Optimise Images
  8. Reduce HTTP-Requests
    1. Combine Print Stylesheet With Main Stylesheet:
    2. Combine Javascript Files:
    3. Use CSS Sprite Sheets:
    4. Use Base-64 Encoded Images:
  9. GZip What You Can
  10. Imitate Background Images With Colours
  11. Write / Output Cleanly Indented HTML
  12. Drop Internet Explorer 6 Support
  13. Do Not Block Browsers for ‘Compatibility’

Jens Mieret publishes a list of general tips on optimising websites for in his opinion speed, simplicity, accessibility and user friendliness.

This presents a lot of valuable information in a very simple way, and therefore as a good idea, it should be stolen borrowed.

Here are, in my opinion, a number of key optimisation tips for your website:

Move Scripts to the Bottom of the Body

When the page loading hits a script tag—everything stops. Scripts have the right of way. A script can’t change the DOM until the HTML has loaded, so more important things like stylesheets are held up loading a script file that’s no actual use until the HTML has finished loading! Get your HTML structure and CSS to the user as quick as you can. The browser will be able to render the page much quicker and then scripts can be loaded, rather than leaving a blank page for the user to stare at whilst they wait for scripts to download.

	⋮
	<script src="js/main.js"></script>
</body>

Moving the script tags to just before the </body> tag alone will make your website noticeably snappier! However, doing this brings added responsibility. Because the page will render before scripts have initialised, particularly quick clickers will be able to interact with your site before your JavaScript is ready! This brings us on to the next tip:

Use async and defer Script Attributes

HTML5 provides two new attributes for <script> tags.

The async attributes causes the script to be executed without the browser waiting for execution to complete before continuing. This means that multiple scripts elements won’t block the browser from downloading other resources and rendering.

<script async src="js/main.js"></script>
<img src="test.png" alt="HTML5 script async means that this image will be downloaded in parallel" />

(though, as noted earlier, your scripts should be at the bottom of the body anyway)

async can be used when you need to load JavaScript libraries which do not modify the DOM (async scripts are run before the DOM is ready) and keep the rest of the page loading.

defer causes the script to wait until the DOM is ready before executing. Use this for scripts that intend to modify the document.

Browser support is weak at the moment, IE supports defer (since v5.5!) and Firefox 3.5 supports async and defer but it doesn’t hurt to add these to your script tags to future proof as new browsers pick up support. Until then, there’s a whole variety of ways you can asynchronously load scripts to gain performance.

Ensure the Site Works With JavaScript Off

I cannot stress this enough, and how much it makes a positive difference—even when JavaScript is enabled! Firstly, more and more people are now browsing with JavaScript switched off by default thanks to the security benefits and flexibility provided by NoScript. It increases browsing speed, frees up bandwidth, increases privacy by blocking all sorts of third party scripts, and helps mitigate XSS attacks.

Just as your HTML and CSS should be separate, so should your JavaScript. If you code your site to work without AJAX first all your server-side events are done, you can just veneer the site with event-bound JavaScript to replace REST events with AJAX ones based on the URLs already in the HTML. Google doesn’t run JavaScript, so it still needs to get around!

Detecting if an incoming HTTP request is coming from AJAX instead of REST is easy too, you don’t have to send any special tokens or headers from your JavaScript code.

if (@$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
	//code to deal with AJAX response
};

Having the site work without JavaScript increases user trust, increases the platforms you support without any extra work, increases SEO, reduces maintenance and best of all, allows people to click through your site at super speed when they know where they want to go.

Provide Proper Fallbacks for Flash Content

Assuming everybody has Flash doesn’t cut the mustard any more, there are more diverse platforms in use—that don’t support Flash—than there were years ago; iPhone for one. People are blocking Flash with AdBlock, NoScript and FlashBlock.

If people can’t see your content then you lose out. There are almost always better ways of presenting content to users without using Flash, and if you have to use Flash then don’t provide a lame cop-out excuse like “Install Flash” as the only fallback message. Describe what the actual content is, why you can’t view it and provide it in an alternative format (such as an image).

This especially applies to videos. I don’t have Flash installed, telling me to install Flash is just annoying, when there’s plenty of other ways you can give me the content. Why don’t you provide a download link for the video file, huh? Even better than that, modern browsers support HTML5 <video> that requires no plugin at all—use that instead!

If you are embedding video you should be using Video for Everybody—a comprehensive solution that uses native HTML5 <video> in browsers that support it, then falls back to Flash for other browsers.

There is no reason anybody should be staring at a broken plugin icon anymore.

Clean Up the Head

You can really fill the head element with junk if you want to.

Don’t use a favicon link:
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />

/favicon.ico is assumed by default, putting this in the head is just extraneous bytes. If you need to store your favicon somewhere else (why? No why? No really, why?) then just mod_rewrite it to /favicon.ico to avoid 404s and wasted HTTP-requests from browsers / aggregators assuming the default.

Don’t use keywords / description:

All SEO is bunk. Paying for SEO ‘specialists’ to wave their magic wand over your site is no more material than a pair of emperor’s clothes. If you have clean, tidy, semantic markup, have avoided text in images and have a sensible and clear system of navigation that doesn’t depend on Javascript, then Google will have no problem understanding your site.

To that end, I have found that filling the head full of keywords is a waste of time. Camen Design appears on Google without any issue. Seriously, drop the voodoo and witch doctors, it’s not the ’90s anymore.

Styleheets First

To give a feel of snappiness, you want to get the structure rendered as soon as possible, ideally before any images have even loaded. It’s critical therefore to get the stylesheet to the user as soon as possible. Any HTTP-requests before the CSS sheet are wasting valuable time!

Therefore, don’t place any <link> or script elements above the stylesheet in the HTML head. If you really want to save a few milliseconds more for dial-up users, put the stylesheet above the <title>!

Add Height & Width on <img> Tags

One thing that really annoys me is when you view a site with a lot of images and as you’re reading, the page is jumping all over the place as the images load. If you define the correct height and width attributes on image tags, then the page will render faster (less reflows) as well as allowing your users to get on with reading without disturbance whilst the images load.

If your HTML is outputted by a CMS and the height and width attributes are not added, then either modify the code to look up the image size (getimagesize in PHP), or hound the developers until they do.

Optimise Images

All imaging software—and especially Adobe Photoshop—output inefficient JPEG and PNG files that waste sometimes even hundreds of kilobytes in needless information. There are a number of tools out there that can losslessly reduce the file size. I’ve seen as much as 1 MB or more saved from a gallery of thumbnails.

ImageOptim

ImageOptim combines multiple PNG (and JPEG) optimisation tools into a simple drag-and-drop interface. Everything it does is lossless, based on optimising the PNG compression parameters and removing excess hidden data (such as EXIF in JPEGs).

Screenshot of ImageOptim

43% bandwidth savings and all you had to do was drag-and-drop!

PNGNQ

pngnq is a command line tool that quantises 24/32-bit PNG files into near-perfect 8-bit PNGs. The results are stunning. It also maintains full alpha transparency, perfect for website graphics! (yes, it is quite surreal having a 256-colour image, with full 256-level alpha, but it works!). Website graphics are not usually going to be using as many colours as a photograph so pngnq is perfect for being extra brutal with saving bytes.

Reduce HTTP-Requests

Bandwidth is not the problem when it comes to speed, even on dial-up. The browser can only do a limited number of simultaneous HTTP requests (usually between 2 and 6). That is the bottleneck that you are fighting against.

By whittling the number of HTTP-requests down to an absolute minimum, you will make the time between one page and the next almost instantaneous.

Think of it this way: in a worst case scenario, a single HTTP-request could take up to a second alone if the server is under heavy load or if the bandwidth is already saturated.

Combine Print Stylesheet With Main Stylesheet:

Even if a stylesheet in the head uses media="print" the browser will still download it regardless. When printing or in print-preview, nothing new can be downloaded, it has to already be in cache. Therefore having a print stylesheet in the HTML head is wasting an HTTP-request!

If you include the CSS print declarations in an @media block in the main stylesheet then the same amount of data is being downloaded, but the number of HTTP-requests is reduced, allowing the browser to be busy downloading something else. If your CSS sheet is gzipped then the size of the combined stylesheet will be less than two separate sheets.

Combine Javascript Files:

Again, being brutal with HTTP-requests, merge JavaScript files into one when publishing.

I once wrote a build-system that ‘compiled’ a web-app by searching through Javascript files and finding instances of a function called $import (which just loaded in the named Javascript file), and replaced the function call with the contents of that file. I used this same method to also combine @import statements in CSS sheets with the imported sheet to combine multiple sheets into one.

Use the YUI Compressor to compress JavaScript files by removing extraneous whitespace and comments &c. Google’s Closure Compiler is a more powerful tool that rewrites the JavaScript file to be as small as possible.

If you’re writing swathes of code that have to be spread across many files, it’s well worth investing time in scripting a decent build system to ‘compile’ the site before uploading to a live environment, or using a server-side language like PHP to do this and then cache the result.

Use CSS Sprite Sheets:

Use sprite sheets to combine various icons and imagery into a single image file. This works wonders in most cases but has a few drawbacks. It’s harder to update your graphics afterwards, and it has some issues with browser zooming if you haven’t left sufficient space around elements. Use this method with the image optimisation methods earlier for solid speed gains.

Use Base-64 Encoded Images:

Most browsers support base-64 encoding (IE8+), and IE6 and 7 can be tricked into supporting it (but this would ideally require a script to automate).

Base-64 encoded images can be placed inline in the HTML or in the CSS:

<style>
	/* notice that in CSS, “\” is used to break lines, though in reality you would probably not use line-breaks */
	img	{background: url("data:image/png;base64,\
		 iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKBAMAAAB/HNKOAAAALVBMVEUAAAD////+/v6ezPpbjrIyicIAadYAZukAZu\
		 4AZvUAZvsAZs0AZswAZcsAZcmXfdS2AAAAAXRSTlMAQObYZgAAAElJREFUeF4VxKENgDAQQNFvUK25BEXOMUHrimUB\
		 EgRbsAeSERpQN8uNwDDkzMPMgC7jFh6E7fzo+3wr71UXZUjPqpCnEoqE7v4Dv7MOC059M/cAAAAASUVORK5CYII=")
		 no-repeat center center;}
</style>

<!-- in HTML “\” is not used because of normal HTML white-space collapsing -->
<img src="data:image/png;base64,
	  iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKBAMAAAB/HNKOAAAALVBMVEUAAAD////+/v6ezPpbjrIyicIAadYAZukAZu
	  4AZvUAZvsAZs0AZswAZcsAZcmXfdS2AAAAAXRSTlMAQObYZgAAAElJREFUeF4VxKENgDAQQNFvUK25BEXOMUHrimUB
	  EgRbsAeSERpQN8uNwDDkzMPMgC7jFh6E7fzo+3wr71UXZUjPqpCnEoqE7v4Dv7MOC059M/cAAAAASUVORK5CYII=" />

There are online converters to get the base-64 string for an image, but I use Image to Data, a nifty droplet that copies the base-64 string of any file you drop on it to the clipboard.

Base-64 encoded images are larger than the original file (by a third), but if you have multiple base-64 images in a stylesheet and then GZip the sheet, the overall gains of less HTTP-requests and GZip acting over multiple files combined will far outweigh the size gain converting to base-64. On this site, it’s the difference between 80 KB of CSS+images, and 22.8 KB for one CSS file with the images inside.

Because of the increase in data size with base-64, it is vital that you optimise the images you are converting as much as possible—every single byte counts. Combine ImageOptim, PNGNQ, base-64 encoding and GZip and you will defy the very Gods with your insane levels of compression.

GZip What You Can

Save bandwidth for both you and the user by compressing text-based content such as HTML, CSS and JavaScript files.

Ideally you should compress the HTML/CSS & JS as part of your build / publishing or caching system (can be done using PHP’s gzencode function). You can then tell Apache to inform browsers that the the content is compressed in your .htaccess file:

AddEncoding gzip .html .css .js

You can alternatively use ob_gzhandler to automatically compress the output when your PHP code has finished running and is sending the results to the browser.

If you don’t want to have to compress your files every time you publish, or force your CSS/JS through PHP every request, you can get the server to compress files during output. Bear in mind though that this will increase CPU usage on the server and might not be ideal under heavy traffic; it’s always better to pre-compress your files.

SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/css text/javascript text/plain

Imitate Background Images With Colours

An effect that adds to the perception of speed is to use the CSS to closely represent the page’s design without images. If you view the page without images, is the page layout still communicated via the same colours?

For everything with a background image, set a matching background-colour to act as a ‘placeholder’ for the image, and where possible, design your HTML structure such that background colours can be used to represent the layout of the site when images are not present.

On Tripology, without images, everything just turns a light shade of blue, and no structure is communicated.

Screenshot of tripology.com without images

Simply put—the website should look almost as good without images, as it should with them.

Screenshot of camendesign.com without images

Write / Output Cleanly Indented HTML

The HTML on this site, in fact, every site I’ve written—CMS or not—has had clean HTML, nicely indented and human-readable. Whilst not necessary for all kinds of site, this particular site is very much designed to encourage reading of the source.

There are other benefits though of outputting clean HTML. It greatly helps with debugging HTML / CSS issues, but really the benefits are not the result, it’s the fact that it takes a keen eye, patience and a lot of love to get a big, heavy 10’000+ line CMS to output perfect HTML and that careful consideration whilst achieving that will ensure that you’ve gone over your codebase with a fine-toothed comb and probably end up fixing and improving tons more than just HTML.

Clean HTML makes for a clean codebase too.

Drop Internet Explorer 6 Support

A number of websites, including Apple’s Mobile Me have already taken the lead in dropping support for Internet Explorer 6. The trend is unavoidable.

Think of it this way:—given that there are more people using Firefox 3 (which passes Acid 2 and supports <canvas>) than IE6, the only users of IE6 who can’t upgrade to a newer version or a better browser entirely are Win9X users and frozen corporate desktops. Anybody at home using IE6 is doing so out of a lack of knowledge that they should install updates, or simply use a better browser.

You are working your arse off, wasting large amounts of time banging your head against IE6 bugs, for a group of people who only need to be shown how to install a better browser. It’s like spending tons of money and effort in healthcare dealing with the effects of a disease, when all the time you have the cure in your hand and just need to give it to the people, or tell them where to get it.

The lack of + and > selectors mean that IE6 won’t go near an element without a class or ID in sight. This is insane to be writing code this way. This website has no IDs, no classes and no DIVs to show that crazy tag-soup is not necessary.

You will be able to produce far greater things if you throw away the millstone around your neck that is IE6 and start learning everything that’s been possible for the last five years.

Do Not Block Browsers for ‘Compatibility’

This is going to be quite controversial coming from me when I’ve just said to you above to drop IE6 support and even my own site does not display correctly with Internet Explorer, but don’t bring up a splash screen that outright blocks Internet Explorer (any version), or any browser for that matter from accessing the content of your site—no matter how pretty said screen looks.

Screenshot of IE6 denial message for momentile.com, cc-by robotjohnny.com

If you don’t like IE6, don’t waste your time writing messages (or drawing pictures) for it (you haven’t got Stockholm syndrome have you?). Would you outright block Lynx users, or Dillo users or any user of an alternative browser that isn’t ‘compatible’ with your site? Why attack only IE6 when the list of browsers that will be compatible with your site is smaller than the list that are not?

The fact your site looks wrong is besides the point, somebody’s life could depend on being able to access the content on your site when all they’ve got is IE6 because of whatever reason. I’ve had to access stuff on my site using IE when on other people’s computers or at a public library. You yourself should know that all that matters is the raw text in those kinds of desperate situations, not how it looks.

Completely blocking any browser—IE6 included—goes against the very nature of HTML and CSS, formats that are designed to be universally accessible and still be readable with even the littlest of support.

If you are really concerned about how your website looks on an eight year old browser (would you honestly still use and support Netscape 6?), then place a message at the top of the page telling the user to upgrade their browser, but don’t hide the content, the text still matters to the user.

If the layout and content is totally broken by IE6’s partial CSS support, then consider using “Universal Internet Explorer CSS”, a stylesheet that provides a back to basics design for IE6 that can communicate the text clearly and forego your complex layout completely, allowing you to focus support on better browsers.


Any suggestions or comments, send them my way;
hit the e-mail link below.