As we now know; CSS is a render blocking resource and the fewer bytes we send down the wire to the browser, the faster it can process and render your content.

Therefore, we can reduce the size of our CSS files by removing any unused styles not needed by the browser. We can take this concept one step further by isolating our critical above-the-fold styles and only sending down what we need to render the top half of the page and declaring everything else as non-critical.

What if we could eliminate the HTTP requests for this critical resource entirely?

2.3.1 Identify critical CSS


As we have learnt, CSS stylesheets are render-blocking, meaning the browser won’t paint content to the screen until all of your CSS – specifically, media=’screen’ CSS – arrives. The solution to this is inlining the initially needed (above-the-fold) critical CSS for your page and loading the rest of your CSS when the page is ready.

The theory behind this is that the reader should get the first screens worth of content to the user in the first few TCP packets of response. Any script or CSS file that is required to display content within the first screen of content is an additional network which will significantly slow down the apparent rendering of the page.

You know your application to best, and should be able to make a decision as to what is inlined and what isn't. Try keeping the resulting CSS to a maximum of 10kb.

Although working out which styles are needed for above-the-fold can be very laborious. Fortunately there is a great bookmarklet we can use to identify these styles.

Drag this bookmarklet link: Above the fold into your browsers toolbar.

  • Open the example-site/index.html page in your browser
  • Run the bookmarklet
  • Open up the browsers JS console alt + ctrl + j
  • You should see the outputted CSS in the console.
  • Highlight the CSS and copy with ctrl + c
  • Edit the index.html file in your favorite text editor.
  • Create a <style> element in the <head> and paste in the CSS.
  • Now move the normal CSS <link> to the bottom of the page.
<!doctype html>
<html>

<head>
    <title>Catz</title>

    <style>
        Your copied CSS goes here!
    </style>
</head>

<body>
<h1>Super awesome cat website</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>

<link rel="stylesheet" href="default.css" />
</body>
                

2.2.2 UnCSS


Using UI frameworks such as Bootstrap is very efficient way of developing. Yet we end up using only 10% of the CSS they provide (when opting for the full build, which most do). As a result, they can end up with fairly bloated stylesheets which can significantly increase page load time and affect performance. grunt-uncss by Addy Osmaniis an attempt to help with by generating a CSS file containing only the CSS used in your project , based on selector testing.

Uncss

Lets see if we can use uncss to remove the unused css in our example site.

  • Open your terminal and change directory to the example site: cd /path/to/perf-workshop/tasks/2_Critical_Path/example-site
  • Install the uncss using npm: npm install grunt-uncss --save
  • Create a new Gruntfile.js
  • Add your new task to the Gruntfile.js and set up the configuration as below.
  • Run the grunt task in your terminal: grunt
  • Now change the CSS link in your example site to reference the newly created optimised file.
module.exports = function(grunt) {

    grunt.initConfig({
        uncss: {
            dist: {
                files: {
                    'tidy-css.css' : ['index.html']
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-uncss');
    grunt.registerTask('default', ['uncss']);
};

Note:

“I just want to ship the CSS required for this page.” is the wrong way to think about this. Instead: “What site-wide CSS am i shipping that isn’t used by any pages.” such as framework bloat is the correct way.

2.2.3 Compare


You should now have an example site with fully optimised CSS: all critical above-the-fold CSS inlined in the head and the optimised bootstrap file in the footer.

These optimisations will shave off ~800ms from the start render and 1sec off visually complete events

This webpagetest comparison results shows the performance gains from this process.
http://www.webpagetest.org/video/compare.php?tests=140217_9B_WXV,140217_D5_WXW

WebPageTest before/after

2.2.4 Automate Advanced


Although using the bookmarklet above is useful to identify your critical CSS, it can be quite tedious having to do this every-time you create or update your websites. As we know: web-developers are lazy and therefore the best things in life should be automated!

Fortunately there are tools out there to help us, such as Critical by Addy Osmani. This uses PhantomJS to load the page into headless browser and abstract the critical CSS into a separate CSS file with just one command line action.

Critical

Try using the JavaScript tool Critical to automate the critical CSS process and inling on our example page.

2.2.5 Async Advanced


Although we have now optimised the loading of our critical CSS in the <head>. We still have to make a large blocking request for the rest of the CSS at the bottom of the page. Unfortunately this will still cause a FOUC (flash of unstyled content) towards the bottom of the page as the CSS is loaded and parsed.

One solution to get around this is to load the rest of your non-critical resources asynchronously using JavaScript. The Filament Group have created a great helper function called loadCSS to help us achieve this.

Try using loadCSS to implement this functionality on our example page.

Once you have done this, use your DevTools network panel and timeline to see the affect on the loading order of your resources.

2.2.6 localStorage Advanced


By inlining our critical CSS we have eliminated a render blocking HTTP request. And by using loadCSS with have made the non-critical CSS resources load asynchronously. Although we still need have to rely on the networking stack to work correectly.

One solution to get around this is to cache your core assets in localStorage the first time they are loaded by the browser. This allows for any subsequent requests to access the file instantly without having to do the networking again.

Basket js

Try using the JavaScript library Basket.js to implement this functionality on our example page.