Glossary

Render-blocking resource

A render-blocking resource is one the browser must download and process before it can paint anything at all. Stylesheets in the head block by design, because rendering with the wrong styles and then correcting them would be worse than waiting. Synchronous scripts block because they can modify the document as it is being parsed. Every such resource adds its full round trip to the time before a visitor sees anything.

Why CSS blocks rendering

The browser cannot construct the render tree until it knows the styles, because an element's computed style determines whether and how it is drawn.

Painting first and restyling afterwards would produce a flash of unstyled content, which was the behaviour of early browsers and is worse than a short delay.

A stylesheet with a `media` attribute that does not match the current context is fetched at low priority and does not block, which is how print stylesheets avoid the cost.

So the size and the number of stylesheets in the head are directly on the critical path, and a stylesheet importing another with `@import` serialises two round trips.

Why scripts block, and what defer and async change

A plain `<script src=...>` in the head stops HTML parsing entirely: the browser must fetch and execute it before continuing, because the script may write to the document.

`defer` tells the browser to fetch the script in parallel and execute it after parsing completes, in document order. This is the right default for application code.

`async` fetches in parallel and executes as soon as it arrives, interrupting parsing at an unpredictable point and in an unpredictable order. It suits independent third-party scripts and nothing that has dependencies.

A script at the end of the body behaves roughly like `defer` for parsing, though it is discovered later, so `defer` in the head is generally better.

Inline scripts always block, and they additionally block on any stylesheet still loading, because they might query computed styles.

What to do about it

Inline the styles needed for the visible part of the page and load the rest asynchronously. This is the critical CSS technique, and it is the largest single improvement available on most sites.

Split stylesheets by media so that only the relevant one blocks.

Add `defer` to every script that does not need to run during parsing, which in practice is nearly all of them.

Remove unused CSS. Most sites ship a framework's full stylesheet and use a fraction of it, and the unused part blocks rendering exactly as much as the used part.

Avoid `@import` in CSS, which turns one round trip into two.

How to find them

PageSpeed Insights and Lighthouse both report render-blocking resources by name with the estimated saving.

In the network panel, resources requested in the first wave with high priority and a blocking marker are the ones concerned.

The coverage panel in the browser's developer tools reports how much of each stylesheet and script was actually used, which quantifies the unused portion.

Compare First Contentful Paint against time to first byte. A large gap with a fast server points squarely at render-blocking resources.

Frequently asked questions

Does CSS block rendering?
Yes, by design. The browser needs the styles before it can build the render tree, and painting unstyled content first would be worse.
What is the difference between defer and async?
Both fetch in parallel. defer executes after parsing, in document order; async executes as soon as it arrives, interrupting parsing in an unpredictable order.
Is a script at the end of the body as good as defer?
Nearly, for parsing. It is discovered later, so the fetch starts later, which makes defer in the head the better choice.

Sources

Related

VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.

Scan a website