How and Why You Should Inline Your Critical CSS

Asha Laxmi
Share

A website stage setting

In the early days of the internet, websites were primarily used to show text based information. Slowly, our connection speeds have improved and users have been able to download high-resolution images and videos fairly quickly. Now websites do a lot more than just provide necessary information in the form of text. Websites are becoming more complicated, with CSS and JavaScript frameworks, plugins galore and more. With all of this in play, loading all the necessary files for all of this can take some time.

A faster website can result in a better user experience, which can make a huge difference in a website’s success. What can developers do to start making performance improvements? One thing that developers can do which helps greatly is to inline critical CSS and load non-critical CSS asynchronously. In this article, we’ll cover these points one-by-one and help you improve your website’s performance.

What is Critical CSS?

The critical CSS in your project is the CSS that’s used to style the above-the-fold content of your website. Above-the-fold content is what users see on your website first, which can include navigation and other elements. So it’s very important to properly style and render this part of the website as quickly as possible.

One thing that I would like to mention here is that your visitors probably use a myriad of devices with different viewports to visit your website. So, above-the-fold content is not going to be of much help by itself. To solve this issue, you should also consider any CSS related to the basic layout and typography to be critical as well.

Modern web development practices often recommend that you inline your critical CSS. It would be placed into your web page like so:

<!doctype html>
<html>
  <head>
    <title>An Optimized Web Page</title>
    <style type="text/css"> (Your minified critical CSS would be here) </style>
  </head>
  <body>
     (Your markup)
  </body>
</html>

Why is Inlining Necessary?

If you head over to Google PageSpeed Insights and analyze one of your web pages, you might see warnings about optimizing your CSS delivery by inlining critical CSS and loading render-blocking stylesheets asynchronously.

Browsers won’t render the above-the-fold content of your web pages unless they have loaded all of your CSS files. This can be a big deal when a lot of files need to be loaded.

Not all of your users will have a fast internet connection and waiting for the libraries, CSS and JavaScript to load before they can actually access the content they came for can be very frustrating. Even users with fast internet can lose connectivity in certain situations, like when they are passing through a tunnel. At this point, they would still be able to access the main content if your website has inlined critical CSS and doesn’t load other files before showing main content.

The image below illustrates the difference between a regular and an optimized web page. As you can see, the optimized version will allow users to access the content about 0.5 seconds earlier. The improvements will be more pronounced when there are a lot of extra libraries that need to be loaded.

Inline CSS loading stages

Should You Inline Critical CSS?

It depends on the situation. If you are not using any heavy frameworks or libraries and your own CSS files also have a small size, then you may not need to inline your CSS.

If you are using a framework like Bootstrap, you are probably not using all the features that the framework offers. In that case, you can just extract the critical CSS from the framework’s stylesheets and load the actual framework asynchronously. This should significantly improve your website’s speed.

While inlining, stylesheets can be cached. HTML often is not cached (it is often not a good idea to do so!). This means there can occasionally be a difference between the two. Keep this in mind when making updates! Also, the inlined CSS will result in some extra page weight every time a user loads your website. For example, if there is 30kB of inline CSS on every page of your website then 10 page views by a single user will cost the user 300kB. It may not sound like a big deal but data is expensive in some parts of the world (and on some 3G/4G data plans). Ensure that the CSS you are planning to inline is genuinely critical to your web page and you are not inlining everything.

Finding Critical CSS

Finding critical CSS manually will be a daunting and boring task. Fortunately, there are tools available that can help you do it quickly.

Using Grunt

If you are familiar with the Grunt build system, there is a plugin which makes this process easier — the popular grunt-critical plugin. If you prefer Gulp or using npm, see the next sections for how to do this process with those.

First, you need to install the plugin using the following command:

npm install grunt-critical --save-dev

You also need to create your Gruntfile.js. This will contain all the code to set various options for the plugin including viewport dimensions and the path to source and destination file. Here is an example:

module.exports = function(grunt) {

  grunt.initConfig({
    critical: {
      extract: {
        options: {
          base: './',
          width: 1024,
          height: 768,
          minify: true
        },
        src: 'path/to/initial.html',
        dest: 'path/to/final.html'
      }
    }
  });

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

};

Inside our wrapper function, we use the grunt.initConfig method to specify all configuration options. In this case, I have specified a base directory in which the source and destination files are to be written. I have also set the minify option to true. This gives me a final minified version of the critical CSS that the plugin extracts. The src property contains the location of our source file which is to be operated against. The dest property contains the location where the final output needs to be saved.

In case the dest file is a stylesheet, the resulting CSS is saved to a file for use in future. However, if the dest property is a markup file (HTML, PHP and so on), then the CSS is inlined and the existing stylesheets are wrapped in a JavaScript function to load them asynchronously. A noscript block is also added for users who have disabled JavaScript. There are other options available as well. You can access the full list of options on critical’s documentation.

Now, you can just run the plugin by typing grunt into the console:

C:\path\to\project>grunt

If your initial file had the following markup:

<!doctype html>
<html>
  <head>
    <title>The Optimizer</title>
    <link rel="stylesheet" href="link/to/stylesheet">
  </head>
  <body>
     <div>All the markup stuff</div>
  </body>
</html>

It will now look like:

<!doctype html>
<html>
  <head>
    <title>The Optimizer</title>
    <style type="text/css">Minified Inlined CSS</style>
    <script id="loadcss">
       JavaScript to load styles asynchronously...
    </script>
    <noscript>
      <link rel="stylesheet" href="link/to/stylesheet">
    </noscript>
  </head>
  <body>
     <div>All the markup stuff</div>
  </body>
</html>

As you can see, this plugin does all your work for you. Now, if you analyze your web page using PageSpeed, you should get a better score. In my case, the score changed from 86 to 95.

There are other plugins available for Grunt that achieve a similar feat — grunt-criticalcss and grunt-penthose. However, when using these plugins you will have to specify the stylesheets from which to extract the critical CSS.

Using npm Modules

Critical is the npm package created by Addy Osmani, it contains the functionality that the grunt-critical plugin uses. You can use it without Grunt to extract and inline critical path or above the fold CSS from a web page using JavaScript and npm. To install the package, you need to run:

npm install critical --save-dev

Once the package has been installed, you need to create a JavaScript file in the project directory and put the following code in it.

var critical = require('critical');

critical.generate({
  inline: true,
  base: 'initial/',
  src: 'homepage.html',
  dest: 'final/homepage.html',
  width: 1366,
  height: 768
});

You can specify a bunch of options to create your optimized web page. Setting inline to true will generate an HTML page with CSS inlined, otherwise a CSS file will be generated. The width and height option set the dimensions of our target viewport. There are a lot of other options like minifying the inlined CSS which you can find on the critical npm package’s documentation. The markup of the optimized web page will look similar to the output by the grunt plugin.

Another npm module that is available for you to use is the critical-css module. This module generates the critical CSS from the supplied URL. The generated CSS can be further processed using a callback function because the grunt plugin is based on this package.

Using Gulp

If you are more comfortable working with Gulp, Addy Osmani recommends Gulp users use the Critical npm module directly. The example he provides on the Critical GitHub page for Gulp users looks like so:

var critical = require('critical').stream;

// Generate & Inline Critical-path CSS
gulp.task('critical', function () {
  return gulp.src('dist/*.html')
    .pipe(critical({base: 'dist/', inline: true, css: ['dist/styles/components.css','dist/styles/main.css']}))
    .pipe(gulp.dest('dist'));
});

The Critical team also have a sample Gulp project showing this in action.

There is also a gulp-critical-css plugin to generate critical CSS. However, this one works by extracting certain selector types from your CSS, rather than by detecting above-the-fold elements and so on.

More Resources

Another tool available is the Critical Path CSS Generator by Jonas Ohlsson. All you have to do is enter your page URL and then supply all the CSS from which you want to extract the critical CSS. Clicking on the “Create Critical Path CSS” button after that will output your CSS.

The article on CSS-Tricks outlines how you can use CSS preprocessors to author critical fold CSS. Additionally, SitePoint has also published an excellent article about optimizing critical rendering path in the past that you can read to gain a deeper understanding of the topic.

Conclusion

Whether you should or shouldn’t inline critical CSS depends on the visiting pattern of your users and the structure of your website. If your website is a one pager and visitors are not going visit it frequently, or if you’ve got a complex site with frameworks and plugins, inlining critical CSS can improve performance significantly.

The only concern about inlining is that it adds additional page weight for each visit. This can be mitigated by using cookies and sending critical CSS only during the first visit while still loading the full CSS file asynchronously and then caching it. It is a little complicated but you get the best of both worlds.

Have you tried inlining CSS in your own projects? How significant were the improvements? Do you have any advice for fellow developers? Let us know in the comments.