My ultimate front-end speed optimisation techniques

This blog post was written by Nick McBurney and published 29th January 2017

This is my ultimate list of front-end optimisation techniques, I’ll explain the common methods and more technical, lesser known techniques which I use to optimise website loading time (and Google PageSpeed scores).

Please note these methods focus entirely on the front-end of your website and will have no impact on slow server responses.

If you’re looking for ways to improve your WordPress theme’s speed Id suggest you also have a look at my earlier post: How I optimised my theme’s speed.

1: Minify CSS & JS

Google describes minifying CSS / JS as the process of removing unnecessary or redundant data such as code comments, white space / formatting and using shorter variable and function names etc. Each character (including empty spaces) in a file is equal to 1 byte of data, so removing the formatting in your files can have a large effect on file size.

Lets take a look at the main stylesheet used by one of my favourite websites: css-tricks.com, the minified version is showing up in Chrome Dev Tools at 28.6KB (at time of writing), if I take this file and un-minify the code then the size balloons up to 167.11KB, thats more than 5 times bigger! This is just one file, if your website is using multiple CSS / JS files then minification can save 100s of KBs.

How to minify your CSS and JS

Depending on what code editor I’m using I have various plugins which I use to minify my CSS/JS each time the file is saved, but there is also lots of websites which can minify your code for you. If you choose to use a web service to minify your code then you should manually create a .min.css or .min.js file extension to hold the minified code, this way you can always go back to the formatted version for editing.

2: Reduce HTTP requests (combine files)

Modern sites can make hundreds of HTTP requests and these can slow down the speed of your site, reducing the number of requests a site makes will help improve the loading time of your website because you are reducing the amount of things the web browser has to request and download before rendering your page.

Say you have three CSS files: header.css, main.css and footer.css, to load these files requires 3 requests to you server, combining these into 1 singular stylesheet means that your site only needs to make the one request to the server. Although you’re not reducing the total size of the files or overall page, the reduction in requests means that files further down the waterfall can be downloaded quicker and the overall load time of your site will improve.

As well as CSS its extremely common for modern websites to load lots of different JS files, both internal and external JS, these files can all be combined into a single JS file which can dramatically reduce requests. Its important to note that the files should be combined in the order they were originally loaded, otherwise you might see that parts of your site no longer work.

For example if your site is using jQuery and you have custom scripts which require jQuery, you could combine your custom JS with jQuery but if jQuery is not the first script in the file then your other JS will likely not work as you’d expect (you’ll see: Uncaught TypeError: $ is not a function(…) within your console) and potentially actually slow down the load time of your website.

3: Replace jQuery with native JS

jQuery is a great tool, it makes coding JavaScript a simpler and faster for developers. But its often used for even the smallest of JavaScript interactions, I’ve seen jQuery loaded just so the developer can add a class to an element on click.

Theres a number of sites out there to help you convert your jQuery functions to native JS. I converted my theme’s JS files from jQuery to native JS and created a list of common functions replicated in native JS which are hopefully useful.

Removing jQuery will help your site load faster because its removing a server request and reducing the total page size by around 32kb, it can also have a very positive effect on your Google Page Score; after I removed jQuery my score went from 69 to 85/100.

4: CSS at the top, JS at the bottom

Putting your CSS stylesheets in the <head> of your website allows the page to render progressively, which will give the user a fast ‘perceived’ load time, in comparison (and I really hope no one is doing this) if you put the CSS at the bottom of the page, then the whole page (including images, scripts etc) needs to be downloaded before any of your styles are applied.

JavaScript should be positioned at the bottom of the page just above the closing </body> tag. This will allow the HTML, CSS and Images to load without being blocked by scripts.

JavaScript files block parallel downloads, which means while the files are downloading / executing the browser won’t download any other files, this can cause the page to initially load without styles and / or images which leads to a slow perceived load time for the user.

When moving files around its important to test your site to ensure you’ve not caused any bugs if you find bugs, theres is usually ways to work around and fix these situations whilst keeping the majority of your JavaScript at the bottom of the page.

5: Remove unused/legacy code and files

Its good practice to review and refactor your websites code and assets to check you’re not using code or files which are no longer required. Your site may have recently dropped support for a certain browser (such as IE8) and you should use this as an opportunity to ensure you’re not loading any specific polyfill scripts or CSS files which all add to the bloat of your webpage.

Many modern websites also use tracking codes / conversion tracking pixels etc to track how their users interaction. Its important when working on a site like this to check if the tracking codes are still be used or if they’ve been replaced, if they’re no longer needed get rid of them!

Tracking codes/images all add extra requests to your site (usually multiple per solution and from various sources) and these all help to slowdown your website, an easy fix for this is to keep up to date with what is being used, what hasn’t been used in a while and discuss with the relevant people whether they still need it including.

6: Inline critical CSS

Inlining CSS can greatly improve the perceived loading time of your site because the browser will apply the inline styles as soon as the DOM element is available, you don’t need to wait for a style sheet to download before rendering. If you’re going to inline your CSS you shouldn’t inline the whole file (unless you have a very small stylesheet – in which case definitely do!) but just the above the fold or critical bits of CSS.

How to inline your CSS into the head of your website (C# & PHP)

To inline CSS in an C# MVC application use the following snippet:

<style>
    @Html.Raw(File.ReadAllText(Server.MapPath("/Content/CSS/criticalCSS.min.css")))
</style>

To inline CSS in a PHP application use the following snippet:

<style>
<?php 
    echo file_get_contents('/Content/CSS/criticalCSS.min.css', true);
?> 
</style>

7: Inline small JavaScript files

If your site uses a small amount of JavaScript then you could inline this just above the </body> tag of your website, this removes the server request and download time of the file. JS files can also be render blocking, and inlining them will remove this problem allowing the browser to render the page faster.

Be sure to test your website after inline JavaScript to ensure you’ve not caused any bugs.

You can inline JS in the same way as we inline our CSS above, heres the code:
Inline CSS in an C# MVC application

<script>
    @Html.Raw(File.ReadAllText(Server.MapPath("Content/JS/myJSFile.min.js")))
</script>

Inline JS in a PHP application

<script>
    <?php echo file_get_contents('/Content/JS/myJSFile.min.js', true); ?> 
</script>

Inline JS in plain HTML

<script>
    // your minified javascript here
</script>

8: Defer non critical CSS & JS

Once you have your critical CSS inlined you can defer the non critical CSS until after the page has finished loading, you can also use this method to defer the loading of JavaScript files which are non-critical for example, if you have a form validation JS file then this can probably wait until the whole page has loaded before being downloaded.

// DELAY SCRIPTS AND CSS FILES
var cb = function() {
	// defer scripts
        var l1 = document.createElement('script'); l1.type = 'text/javascript';
	l1.src = '/js/non-critical-js.js';
	var h1 = document.getElementsByTagName('head')[0]; h1.parentNode.insertBefore(l1, h1);
	var h1 = document.getElementsByTagName('head')[0]; h2.parentNode.insertBefore(l1, h1);

        // defer css	
	var l2 = document.createElement('link'); l2.rel = 'stylesheet';
	l2.href = '/css/non-critical-css.css';
	var h2 = document.getElementsByTagName('head')[0]; h2.parentNode.insertBefore(l2, h2);
};

var raf = requestAnimationFrame || mozRequestAnimationFrame || webkitRequestAnimationFrame || msRequestAnimationFrame;
if (raf) raf(cb);
else window.addEventListener('load', cb);

9: Use media queries to download files depending on requirements

I recently came across this method and although its not the right solution for everything it can be powerful if you have different designs and requirements for desktop/mobile. A site I recently worked on had an a carousel being used on mobile devices, the carousel was about half way down the page on mobiles and in desktop the content was shown as a simple list. I was initially loading the JS / CSS required for the carousel once the page had finished loading, but files were being downloaded on desktops even though they weren’t required for the page.

So I started looking into ways to stop the loading of files based on if they were required or not, and came across the use of the media="" property which can be used for CSS and Js files. See example:

<link rel="stylesheet" 
    type="text/css" 
    href="/Content/CSS/mobile.min.css" 
    media="screen and (max-width: 675px)" 
/>

This didn’t stop the file being downloaded on desktop devices but it did reduce the priority so the file would be loaded last instead of in the order it was listed in the HTML.

This was an improvement but this solution didn’t stop the file for downloading and also this option isn’t compatible with all browsers, some of which will just ignore the media property and download the file in the order its called. My next step was to look for a native JS solution which would either download the file (if required) or completely ignore the file if not needed by the page. I found this snippet of JS:

(function () {
    var queries = document.querySelectorAll('.mediaquerydependent'),
        all = queries.length,
        cur = null,
        attr = null;
    while (all--) {
        cur = queries[all];
        if (cur.dataset.media &&
            window.matchMedia(cur.dataset.media).matches) {
            for (attr in cur.dataset) {
                if (attr !== 'media') {
                    cur.setAttribute(attr, cur.dataset[attr]);
                }
            }
        }
    }
}());

To use this snippet of native JavaScript I need to update my <link/> changing the href property to a data-href and adding a ‘mediaquerydependent’ class as below:

<link rel="stylesheet" 
    type="text/css" 
    class="mediaquerydependent"
    data-href="/Content/CSS/mobile.min.css" 
    media="screen and (max-width: 675px)" 
/>

The Javascript above will look for all tags with the ‘mediaquerydependent’ class, check the media property ensuring the media query passes, then get the data-href and use this to update the regular href after which the browser will download the file.

This JS snippet can also be used to check the media query for JavaScript files, you just need to add the ‘mediaquerydependent’ class and change the src property to data-src like this:

<script type="text/javascript" 
    class="mediaquerydependent" 
    data-src="../JS/mobile.min.js" 
    data-media="screen and (max-width: 675px)"></script>

10: Replace images with CSS

Some older sites still use images for background gradients and rounded corners, these effects can all be achieved with CSS3 and are widely supported by browsers.

CSS Background Gradients

/* Opera 15+, Chrome 25+, IE 10+, Firefox 16+, Safari 6.1+, iOS 7+, Android 4.4+ */
background: linear-gradient(90deg, rgb(22, 135, 237), rgb(20, 55, 90));

/* Safari 5.1, iOS 5.0-6.1, Chrome 10-25, Android 4.0-4.3 */
background: -webkit-linear-gradient(90deg, rgb(22, 135, 237), rgb(20, 55, 90));

For improved browser support, try this gradient generator.

CSS Rounded Corners

CSS rounded corners use very simple syntax:

-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;

For more complex situations, try this generator.

11: Compress images

This is a really simple one, every time you’re adding an image to your site, you should ensure it has been compressed before uploading. Compression can hugely reduce the size of images usually reducing file size between 30-80%. I use a few different websites to compress images: TinyJpg.com and CompressJpeg.com.

If you’re running a WordPress site take a look at WP Smush, which will automatically compress images on upload.

12: Use sprite sheets

Sprite sheets can have a really great impact on your site’s loading time. In the same way as you should combine your CSS and JS files, you should combine your images into sprite sheets  to save on requests.

Sprite sheets aren’t ideal for everything but if your site has lots of common shared icons (such as home, search and social icons) then sprite sheets are an excellent way to improve site load time and speed scores.

If your working with sprite sheets I’d recommend you have a look at: spritecow.com, which certainly makes my life easier.

13: Use a combination of sprites, icon fonts, SVG and base64 images

Image sprites are a great step in the right direction but you can further improve your image loading by using a combination of image sprites, icon fonts, svg icons / svg image sprites and base64 inline images.

If you have an image sprite which is used only for icons then you could convert this into an icon font which can further reduce the file size (especially if you use SVG icons), my favourite tool for creating icon fonts is: https://icomoon.io/app/

You might have some critical images which are very small, these could be good candidates for inline base64 images, these are coded right into your CSS file and remove a server request which will help improve loading time. Its important to only base64 certain images, as the base64 code will increase the size of your CSS file so you don’t want to go putting in huge base64 code strings. My favourite tool for creating base64 images is: http://b64.io/, simple drag you image onto the site and it will generate the base64 code for you.

Some image sprites may contain photographs but if your sprite image is just used for transparent icons / vector images then you can reduce the size of your sprite image by using an SVG sprite image, this will reduce your file size and mean your imagery can be scaled to any size with out distortion / degradation

By using different formats / optimisation methods on your images you can help save precious KBs and keep your site loading fast.

14: Defer non-critical images

Images often make up a large portion of a page’s total size and large images can dramatically slow down your web page. If you have images below the fold then one option is to defer the loading of these images until the rest of the page has loaded. This technique will load all other resources and once the page load event has been triggered (telling the browser the page has finished loading) it will then download the deferred images.

A site I was optimising recently had a blog section at the bottom of most of its pages, these were not critical to the rest of the page, loaded large images and were a perfect candidate for deferred image loading.

To defer the loading of our images we use a simple bit of vanilla JavaScript in the footer of our page and a class to apply to images we want to defer.

HTML setup

We’re using a class named ‘deferload’ to tell our JavaScript which images we want to defer, we give the image a src image using a base64 encoded transparent 1×1 pixel, this pixel will be rendered and ensure the browser doesn’t throw and errors.

<img class="deferload" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
    data-src="/Content/images/my-cool-image.jpg" 
    width="1000" height="580" 
/>

JavaScript Function

This native JavaScript function will look for all images on the page with the class ‘deferload’, if it finds any images with the class it checks their ‘data-src’ property and uses this to replace the ‘src’ property, once this is updated the browser will then download the image from the specified URL.

// DEFER IMAGES FUNCTION
function deferImages(){
	// get all images with 'deferload' class
	var $images = document.querySelectorAll("img.deferload");
	
	// if there are images on the page run through each and update src
	if($images.length > 0) {
		for (var i = 0, len = $images.length; i < len; i++) {
			
			// get url from each image
			var image_url = $images[i].getAttribute("data-src");
			// set image src 
			$images[i].src = image_url;
		}
	}
	console.log("Images loaded")
}


// PAGE LOADED
window.addEventListener('load', function() {
	// run defer image function
   deferImages();
}, false);

15: Set image sizes

Another really simple optimisation technique – this wont have a great effect on your loading speed, but it is a best practice which I recommend. If you’re using <img> tags on your page then make sure they have their width and height set, this means the browser doesn’t need to try and figure out the size of the image and saves a tiny bit of CPU.

Tip: add this CSS to your stylesheet to ensure images scale correctly:

img {
   max-width: 100℅;
   height: auto
}

16: Don’t allow unnecessary background images to download

This is quite an easy one to miss, I (wrongly) assumed if I used display: none on an element with a background image that the image would not be downloaded by the browser. So I used this method to hide desktop images for mobile devices…Oh how naive I was.

I later came across these tests, and experimented myself. As the tests suggested, images would be downloaded by most browsers if I just hid them using the display property, to get around this I started adding background-image: none; which successfully stops all browsers from downloading images which aren’t displayed.

If you’re page uses a featured image displayed at all screen sizes then you should create a number of size variations for the image and replace the image at different break points, this means smaller files can be downloaded for sfmaller screens, saving on bandwidth and keeping you site speedy on any device.

17: Enable Gzip compression

Gzip compression can reduce the size of a web page to about 30% of its original size, by compressing files such as HTML, PHP, JavaScript and CSS. The compressed file is sent to the browser which then decompresses and loads the file. Enabling Gzip compression is one of the best and easiest ways to improve page speed because it makes the web page much smaller to download.

Enable Gzip for Apache

Add the code below to your .htaccess file which should be located in the root folder of your website. Not all web hosts have these Apache modules enabled on their servers, so if the code below doesn’t work try asking them about it.

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE image/x-icon
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/x-font
  AddOutputFilterByType DEFLATE application/x-font-truetype
  AddOutputFilterByType DEFLATE application/x-font-ttf
  AddOutputFilterByType DEFLATE application/x-font-otf
  AddOutputFilterByType DEFLATE application/x-font-opentype
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
  AddOutputFilterByType DEFLATE font/ttf
  AddOutputFilterByType DEFLATE font/otf
  AddOutputFilterByType DEFLATE font/opentype

# For Olders Browsers Which Can't Handle Compression
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
</IfModule>

Tip: If you don’t want to compress a certain file type, just remove the relevant file type from the .htaccess file.

Enable Gzip for Windows server

When your site is hosted on a Windows server you can enable compression for both static and dynamic files using the IIS manager:

  1. Open up IIS Manager
  2. Click on the site you want to enable compression for
  3. Click on Compression (under IIS)
  4. Enable static compression and you are done!

18: Check for broken requests

Your website will make requests to your server (and 3rd party servers) to download files necessary for the web page, sometimes these files can be removed and this will cause a broken request. At best this will slow your page load time with an effectively unnecessary request and at worst completely break your website.

A bad request will slow your page load time because it will actually connect to the server (HTTP request) twice. On the first request the browser will check to see if the file is available, if the file isn’t found then the browser will check again to confirm the file really isn’t available. These additional requests can slow down your page significantly.

How to check for bad requests

You can check for bad requests using the console log in your browser’s web development tools. if a file cant be found then you’ll see the missing file shown as a red console error.

Conclusion

Using just some of these techniques can have impressive effects on your website loading time, they might not all work for you and some are more difficult to implement than others but give them a go and see what results you get.

Im sure theres lots i’ve missed and ill continue adding to this list as I learn more front-end optimisation techniques.

Let me know what you think

Your email address will not be published. Required fields are marked *