Faster webpage loading with critical CSS

If you like to stay on top of things when it comes to optimizing your website performance then it’s almost certain that you’ve heard the term "render blocking CSS". What this means is that by default CSS is treated as a render blocking resource – if you’re loading a webpage the browser won’t let you see it until all the necessary stylesheets are loaded because if it didn’t you’d end up seeing the bare HTML slowly taking form as the CSS loads, which looks unprofessional and is a bit confusing for the user. Of course, there are ways to speed up this process; most users will be familiar with using media queries to ensure only certain styles are loaded depending on device and screen size, but there’s still going to be a main website file which the browser needs to load before the usually-blank loading screen is replaced with the fully-realized website. For this side of things there are alternatives like merging multiple files into one to reduce the number of server requests, or minifying your code; that is, removing white space and redundant elements of the code to make the CSS file lighter and faster to load. But is there anything else you can do? There is, in fact, other ways of getting your site optimized even further with critical CSS, but we’ll get to that shortly; first we need to refresh our memories on exactly how the loading process works.

CSS Object Model (CSSOM)

So you enter a URL in your browser and get moving; what happens now? The first significant thing that your browser will do is create a DOM (Document Object Model); it’s the basic frame of the site, but not enough to show the page. For the second step the browser creates a CSSOM (CSS Object Model) which loads all the files that have been declared in a link HTML tag and does a bit of cross-referencing to assign the correct styles to each of the DOM elements. If you’re interested in getting a bit more info on this, then the loading website workflow is effectively explained via Google Developers -Document Object Model.

Render blocking resources

As mentioned way back at the start of the article we noted that CSS is a render blocking resource, as opposed to JavaScript which may be loaded asynchronously. So if this works for JavaScript, how come we can’t do it with CSS too? The answer is; we can! We just need few lines of JavaScript code to do this; but there’s a problem (there’s always a problem…); this shows the plain core website (without any styles loaded) at first, and once the CSS finishes loading the page will just flash into it’s full form. As you might expect this is the online equivalent of that getting food stuck between your teeth; embarrassing for you, uncomfortable for your customers, and no-one comes away happy!

You probably already know that browsers can cache CSS after the first load to speed things up on a revisit, but how can we get this kind of speed in the initial page visit?

Before moving on, take a minute to have a look at the Google Page Speed tool; if you’re interested in getting your website up to speed it’s a valuable resource that provides many useful tips to help you on your way. What we discover is that the most pressing issue is related with moving CSS files to the HEAD area of your page. When you load all the files one-by-one via a link attribute in the head section you get around this issue but create a new one at the same time (if the whole "solving a problem creates a new one" thing seems bewildering, all we can say is "Welcome to CSS"!); you’ll now have even more render-blocking CSS to reduce down. So you do. And then you have to move the files to the HEAD section. And then you get around it by linking them in the HEAD. But then you have more render-blocking CSS to deal with, so…well, you get the idea. Sounds like an infinite loop? Yes, but we know how to resolve this already; we can separate critical CSS from the rest of the CSS file and load it as inline styles before asynchronously loading the rest of the CSS.

How to find out which CSS is critical?

By critical CSS, what we mean is the absolute bare minimum amount of CSS necessary to see the part of the website currently in the viewport of your browser as intended. This gives us another variable to account for in that we need to know the optimal window size. Unfortunately there’s no hard and fast rule for this that we can fall back on, but we’d recommend that you just use the most popular and widespread screen resolution on your page (You can use Google Analytics or similar to get an idea of how big that resolution will be) or failing that just use the biggest one; 1920×1080 is probably enough in this case.

Now we can go hunting for our critical CSS. If your website has more than few subpages it will likely be hard to find and figure out what CSS should be taking priority, but there are some tools which can help you get the job done. Naturally, we’re only looking for critical CSS from the homepage (or most popular landing page) because once that’s loaded you can use .htaccess rules to cache the file so it will not be loaded from a remote host, which will speed the process up significantly. Here, we strongly recommend using Grunt – The JavaScript Task Runner and a custom task for it called grunt-criticalcss which is available on GitHub.

If you are not familiar with Grunt you should start here Grunt – Getting Started or if you’re familiar with an alternative tool like Gulp or Brunch you can use those.

The configuration of the grunt-criticalcss task is very simple; the most important parts are your page URL and the aforementioned screen dimension which is used to find the necessary CSS rules. The basic task configuration is described in detail on the repository page should you need a hand, and most users shouldn’t need to even take a look at any of the more advanced configuration options when you’re just getting started. When the task is run it will create two CSS files, one of which is called critical which contains the necessary CSS to load the page to a useable fashion. The location of this file may be specified in the task settings in the outputfile parameter*. The content of this file should be placed in the HEAD section of your site between regular style tags. After this step we’ve almost finished – the critical part is loaded and we only need to take care of asynchronously loading the rest of the CSS.

Load CSS asynchronously

There are multiple ways to include stylesheets in your document using JavaScript but the most convenient way is to use a small function called loadCSS which will do the job just fine. This very small function is available on GitHub and you should inline this code in your head section to test that it is functioning correctly before you make an attempt to use it.

An example use scenario is simpler than you might think; in your website script you need to include just one line:

loadCSS( "path/to/mystylesheet.css" );

and of course replace the placeholder path name with the correct path to your original CSS file. I strongly recommend to use this solution only on the homepage for a few reasons. Firstly, the homepage is the most popular start page for your website; sure, there are exceptions but they are few and far between, so focusing on getting your homepage as speedy as possible is the logical solution. Secondly, when your visitor opens the homepage the loadCSS function includes external CSS which your browser automatically stores in its cache, so going through the whole process on every page simply isn’t necessary because loading files from local browser memory will not affect to your website performance.

If you don’t want to use the loadCSS function you can use some other hack like loading the CSS with a media="none" attribute. How does it work? As we mentioned earlier, media queries may unblock the render process because files are loaded only for the particular media in question. With the none parameter you can say to the browser that this CSS is not necessary and it may be loaded in background. The tricky part is to change the media attribute via JavaScript after loading, and you can do this with just one line. In an example provided by Keith Clark all that you need to do is load CSS with this type of link element:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'"> 

The onload event will change a ‘none’ value to ‘all’, so all those ignored CSS styles will now be loaded, but only after you’ve got your critical elements sorted.

That’s all for now; we hope you’ve gained a bit of knowledge from this short tutorial, and do let us know how you get on in the comments below; hopefully you’ll get a few additional points in the Google Page Speed tool!

Share
This article was first published April 24th, 2015