Trying to convince your company to make site load speed improvements? Maybe Google Analytics can help.
How to Eliminate Render-Blocking Resources: a Deep Dive
You might be here because Lighthouse told you to "eliminate render-blocking resources". Render-blocking resources are a common hurdle to rendering your page faster. They impact your Web Vitals which now impact your SEO. Slow render times also frustrate your users and can cause them to abandon your page.
I worked with one client to reduce their render-blocking resources and improved their site loading speed. We went from 13% to 80% of page visits experiencing First Contentful Paint (FCP) in less than 1.8 seconds. And we're not done yet!
Understanding render-blocking resources will enable you to fix this common web performance issue. In this post, you will learn:
- What the critical rendering path is
- What render-blocking resources are
- Why they are important to performance
- How to test and measure your website
- How to fix this issue
Before we continue, we need to take a step back and understand what the critical rendering path is.
What is the critical rendering path? #
- Download the HTML
- Read the HTML, and concurrently:
- Construct the Document Object Model (DOM)
- Notice a
<link>tag for a stylesheet and download the CSS
- Read the CSS and construct the CSS Object Model (CSSOM)
- Combine the DOM and the CSSOM into a render tree
- Using the render tree, compute the layout (size and position of each element)
- Paint, or render, the pixels on the page
We want this process to go as fast as possible. Can you guess what makes it go slower?
What are render-blocking resources? #
Render-blocking resources are files that "press pause" on the critical rendering path. They interrupt one or more of the steps.
HTML is technically render blocking because you need it to create the DOM. Without the HTML we would not even have a page to render.
However, HTML is not usually the cause of our problems...
CSS is render blocking. The browser needs it before it can create the CSSOM, which blocks all later steps. As soon as the browser encounters a stylesheet
<style> tag, it must download and parse the contents. Then it must create the CSSOM before the rest of the render can continue. You can see this represented at the triangle point in the diagram. The render tree cannot continue until both the CSSOM and DOM are created.
Why is it so important to eliminate render-blocking resources? #
Render-blocking resources can trigger a cascade of failures for web performance. First paint gets slowed down which causes Largest Contentful Paint (LCP) to be slower. LCP is one of the Core Web Vitals which are now used to calculate your search engine rankings.
SEO is important for discovery of your website. Performance is critical for keeping a visitor on your page. Page abandonment increases significantly if the page doesn't load within 3 seconds. Many companies have seen significant increases in conversions after improving performance.
Vodafone improved their LCP by 31%, resulting in an 8% increase in sales, a 15% increase in their lead to visit rate, and an 11% increase in their cart to visit rate.
WPO stats lists many cases where improving performance resulted in real business impacts.
How do I test my website for render-blocking resources? #
If you failed this metric in Lighthouse, then you've already discovered one way to test for this. If you're new to Lighthouse, then check out the official Lighthouse page to get started.
We all have render-blocking resources on our sites (all the CSS!). The problem comes in when it significantly impacts our performance. When this occurs, Lighthouse flags it, and we should do something about it.
Lighthouse candidates for render-blocking resources include both scripts and styles:
<script>tags in the
<head>which do not have at least one of the following attributes:
<link>tags in the
disabledattribute or a media query which does not match (e.g.,
If you fail this metric, your Lighthouse results will look something like this:
Lighthouse lists the Google Fonts stylesheet followed by a JQuery script. Let's dig in some more. Let's inspect the
<head> on that sample failure site. It shows us 3 stylesheets followed by 3 scripts, then 2 more stylesheets:
<title>Lighthouse performance audit failures</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles/bootstrap-grid.css">
<link rel="stylesheet" href="styles/bootstrap-reboot.css">
<link href="https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i" rel="stylesheet">
<link href="styles/main.css" type="text/css" rel="stylesheet" media="screen,print">
<link href="styles/bootstrap.css" type="text/css" rel="stylesheet" media="screen,print">
Lighthouse could have flagged any one of those 3 initial stylesheets. The root cause of this failure is:
- The first 3 stylesheets block the 3 synchronous scripts from running. The browser must first download the stylesheet and create the CSSOM.
- The browser cannot construct the rest of the DOM until it downloads, parses, and executes the 3 scripts.
We're digging a deep hole here.
Another way to test for render-blocking resources is to use WebPageTest. WebPageTest is the next step up in performance profiling. If you enter a URL, it will run a performance test on a real mobile device. Once the test finishes, click on the waterfall for the median run. Every render-blocking resource will have an orange circle with a white X next to its row:
Check out the official WebPageTest docs for more detailed information to get started.
How do I remove render-blocking resources? #
Deep-dive: optimizing CSS for the critical rendering path #
For our CSS, we want to
- Minimize the size of our styles
- Deliver them to the client quickly and effectively
That sample failure site is great. I need to buy whoever built it a beer. It's so juicy with performance problems. Let's take a step back and observe all the stylesheet tags. We can see that this website is using Bootstrap and a lot of Bootstrap dependencies as well as 12 Google fonts. It also has screen and print styles combined into single CSS files.
The first question I would ask is:
Do I need all those dependencies?
Don't skip that first question. The easiest way to minimize total size for any asset is to annihilate it. Raze it to the ground. For example, 12 Google fonts seems excessive. I try to keep my web fonts down to 3-4 style sets max.
The next easiest way to minimize total CSS is to, well, minimize it. Minification is the process by which a build tool removes unused white space. Fewer characters = smaller size = faster download. If you're using a CSS package, make sure you use the minified version of it. The next step up is to use a build tool to automatically minimize all your CSS. Example tools include Gulp, Grunt, webpack, and Parcel. Snowpack and Vite are interesting newer tools.
- Open Dev Tools
- Press Cmd + Shift + P to open the quick menu
- Type "Coverage" and then select "Show Coverage"
The drawer will open up for you, and you can click the reload button to start a new coverage analysis. Here is an example from the New York Times website:
If your total CSS bytes are small, then the unused percentage becomes less important. For example, my home page is around 57% unused. Because my total CSS is small, my Lighthouse scores are still around 97-100.
Note that it's only accurate for the styles (or scripts) used thus far. As you interact or resize the page, those numbers will go up.
Your goal is not necessarily 0% unused. However, if you see big red bars and high unused bytes, it's time to reduce the CSS needed for initial render. Remove dependencies, use code splitting, or inline critical CSS and defer the rest. For those last two options, you definitely want to use a build tool. Check out Extract critical CSS for more details including popular tools.
If you have a lot of non-screen styles, consider extracting them to their own stylesheet. Then use a media query on the
<link> tag. For example:
<link href="styles/main.css" type="text/css" rel="stylesheet" media="screen">
<!-- Only downloaded for print: -->
<link href="styles/main_print.css" type="text/css" rel="stylesheet" media="print">
Finally, do not use
@import in your stylesheets to load more stylesheets. The browser won't discover it until later. It's best to load them with
<link> tags in your HTML.
- Minimize the size of our scripts
- Deliver them to the client quickly and effectively
Do I need all those dependencies?
- no attributes: The HTML parser is blocked during script download and execution.
- defer: The HTML parser is not blocked. The browser downloads scripts as it identifies them. It only executes the scripts once it finishes creating the DOM.
- async: The HTML parser is blocked during script execution. The browser downloads scripts as it identifies them. After download, the scripts block the HTML parser until execution finishes.
- module: Behaves like defer but can manage ES6 module imports.
Choose wisely. In most cases you will want either
async to optimize the critical rendering path. If you have an inline script which must run synchronously, test moving it above your styles in your HTML.
Render-blocking resources can kick off a cascade of performance issues. Those performance issues result in unhappy users who abandon your page faster.
Lighthouse and the Coverage tool can help you identify this issue and evaluate what your best options are. We learned to:
- use the
moduleattribute on our scripts.
I'd love to hear what worked for you! Tweet at me with your replies.
Fixing web performance issues can be overwhelming. If you need more help, I'm available for performance consulting projects. Contact me today!
Hi, I'm Sia.
I'm a freelance performance engineer and web developer, and I'm available for your projects.Hire me
You might also like
Thank you for this. But for many of us Wordpress and it’s plug-ins are the impossible-to-fix problem #wordpress
There are some existing posts that cover this topic specifically for wordpress - maybe try them out?
I do know that a lot of the plugins have a lot of bloat. Profile your site and then try to replace the worst offenders with more performant ones.
Good article. I really like the diagrams.
Thanks so much!
Aw, thanks so much!!
Amazing job, @TheGreenGreek !
Thank you for this. But for many of us Wordpress and it’s plug-ins are the impossible-to-fix problem #wordpress source
There are some existing posts that cover this topic specifically for wordpress - maybe try them out? I do know that a lot of the plugins have a lot of bloat. Profile your site and then try to replace the worst offenders with more performant ones. source
Good article. I really like the diagrams. source
Thanks so much! source
SO GOOD! source
Aw, thanks so much!! source
Amazing job, @TheGreenGreek ! source