If you have ever tested your website using Google PageSpeed Insights, you might be familiar with this warning – eliminate render-blocking resources.
If you are also struggling with the same issue, this post will help you. In this post, I will show you how I managed to solve this problem on this website thereby increasing the PageSpeed score from 76 to 94.
What is rendering & How it gets blocked?
You know that a web page is made up of HTML markup. When you visit a website, your browser parses this HTML and renders (displays) it on the screen. However, this HTML usually calls additional resource files like stylesheets (CSS) and scripts (JS) which add design and functionality to the webpage.
Usually, the link to these external resources appear in the head section, that is, before any content. So when the browser comes across any such files, it stops rendering to download and parse them. After that, the rendering resumes.
Why is it a problem?
From a performance perspective, linking to CSS and JS in the head is not a good idea as it can slow down page loading. If you have a number of such render-blocking resources, your visitors have to wait for more time to start seeing the actual content. PageSpeed Insights and Lighthouse shows two metrics to denote this initial rendering:
- First Contentful Paint – the time at which rendering starts
- First Meaningful Paint – the time at which something useful has rendered
So, any delay in the rendering process makes your users feel that your website is slow.
However, adhering to all the suggestions given by PageSpeed may not be always practical as it can affect the usability and maintainability of your site. It is not always necessary. So, use these guidelines to identify serious performance issues and address them.
Steps to remove render-blocking CSS & JS
I used this same blog to try these optimizations. As you can see below, removing render-blocking files alone increased the overall score from 76 to 94.
These were the results before doing any optimizations. There were a total of fourteen files in the head, which is not that good.
Our aim is to get rid of all the external CSS & JS resources from the head. These are the steps to achieve that.
- Install Autoptimize Plugin
- Combine CSS
- Preload CSS file & implement loadCSS
- Finding & Inlining Critical CSS
1. Install Autoptimize Plugin
Autoptimize is our main tool here. It helps us in doing all the things mentioned above. So, the first step is to install and activate it.
Before dealing with CSS, let us optimize JS. For that, go to Settings > Autoptimize. Make sure that you have enabled the Show advanced settings option.
- Aggregate JS-files – combines the files into one and move it to the footer so that it is non-blocking.
After that, hit Save Changes & Empty Cache.
Moving JS to footer alone improved load times and raised our score to 89.
Minifying and combining JS files can break things. In such a case, you have an option to exclude individual files from being optimized.
Another thing is that combining and moving jQuery to the footer can break inline scripts which depend on it. If that is the case, you can extract jQuery-dependent JS and load it later.
3. Combine & Minify CSS
Results after combining CSS:
4. Defer CSS & Implement loadCSS
Combining multiple CSS files has helped to reduce the number of resources, thereby reducing the number of network round-trips to fetch stylesheets. That’s why the scores have improved.
Yet, the combined and optimized CSS is still called via the usual
rel="stylesheet" link element.
Recent browsers support a new value called
preload for the
rel attribute. It helps to access resources for future use without affecting performance. So, moving our optimized CSS to a preload element instead of the stylesheet can make it non-blocking because the browser will not parse resource in the preload link element. This is what PageSpeed suggests to do by deferring CSS.
onload attribute to change the
rel value from preload to stylesheet, so that the browser can parse our CSS.
Again, Autoptimize has the option to implement deferring too, so that you don’t have to touch any code. Go and check the box against Inline & Defer CSS, and then click Save.
Thus, we have completely removes all blocking CSS from the head.
Results after deferring CSS:
Although we have deferred our big external CSS file, we still have two more render-blocking files which are non-local. That’s why the score did not improve much from the previous. Autoptimize will not combine non-local files for a good reason. So let us keep it like that.
However, there is another issue. Since the browser starts to render content before parsing CSS, users initially see an unstyled web-page. Everything comes into place once the CSS gets loaded. This is known as flash-of-unstyled-content (FOUC).
To solve FOUC, we have to implement Critical Path CSS.
5. Finding & Inlining Critical CSS
With the above step, we have deferred CSS. However, it degrades user experience as your visitors can see unstyled content for a moment. So we have to find critical CSS and inline it in the head.
What is Critical Path CSS?
Simply, it is that portion of CSS necessary to style the contents above the fold. In other words, it is the minimum required CSS to style elements like site navigation, page headers, and contents on the top of a page.
Inlining critical path CSS directly in the head reduces the chances for your visitors seeing a flash of unstyled content.
Extracting Critical CSS
Guessing the critical CSS is not that easy. Fortunately, there are a few tools to help us here. Critical CSS generator by Jonas extracts the CSS based on a URL.
First of all, enter the URL of the page. Open your Autoptimized CSS in a new window and copy-paste all its contents in the box on the left side. Then click the button which says Generate Critical Path CSS.
Now, we have generated the CSS for home page. Save it in a file called critical-home.css.
Combining CSS for Different Pages
If you have a static front page or custom-designed archives, your site has more than one layout. That means critical CSS also differs. So repeat the same procedure for any pages that look considerably different.
Now, we have multiple CSS files like:
and so on…
However, Autoptimize gives only one field to enter the inline CSS for all of your web-pages. So we have to combine them into one file.
The following NPM package has helped me to remove duplicate style rules from multiple CSS files and merge it. If you use Node, it is one of the easiest methods to combine and shorten multiple critical path CSS files.
If you are not familiar with NPM or Node, you can use an online tool like DiffChecker to compare different files. Then you can manually copy the additional rules from each file to one file using Notepad or an
Now, come back to your Autoptimize plugin page where you can see a text field to enter the CSS to inline.
Copy and paste the contents of the combined critical CSS file in that field and click Save.
After inlining, we have could pass the test and remove the warning. Remember that we had two non-local blocking resources which could not be deferred. After inlining, those two resources also got deferred.
Why not Inline all CSS?
Below the field for inline CSS in Autoptimize, you can see an option asking whether you want to inline all CSS. The problem is, inline CSS increases the size of the HTML response. So it is not a good idea unless you have a lightweight website with only a few lines of CSS rules.
Since the browser does not cache inline CSS, your visitor has to download all those heavy CSS for each page view. That’s why we inline only the minimum CSS and defer the heavy external file. The browser can cache the external file for subsequent page views. Thus, we have the best of both worlds.
With these optimizations, we could completely remove the warning in PageSpeed Insights to remove render blocking CSS & JS. You can also see that our initial rendering also saw great improvement.
|First Contentful Paint||3s||0.8s|
|First Meaningful Paint||3.2s||0.8s|
|First CPU Idle||3.6s||3.0s|
|Time to Interactive||3.8s||4.0s|
|Estimated Input Latency||10ms||20ms|
Note that the Time to Interactive increased a bit and shows a warning. The Input Latency also went up. That may be partly due to testing inconsistencies and partly because we haven’t removed unused CSS before optimizing. That is a subject for another article.
Our aim was to remove render blocking resources and we have succeeded in doing that.
Wrapping it Up
We have seen how render blocking can adversely affect the load time and performance score of a website. Solving it may seem a bit daunting at first. However, it is worth the try even if you cannot perfectly implement it.