Skip to content
CWV Checker

How to eliminate render-blocking CSS and JS

Render-blocking files stop the browser painting anything. Here's how to work out which ones matter and how to defer the rest.

What is being blocked, and why

Before a browser paints anything it needs to know how the content will look. A stylesheet in the <head> is a promise that styles are coming, so the browser waits rather than showing text that will immediately restyle. A plain <script> tag stops HTML parsing dead at the point it appears.

The result is a blank screen for as long as the slowest blocking file takes to arrive. That time is added to LCP and to First Contentful Paint, and if the blocking file is on another domain you also pay for a DNS lookup and a TLS handshake first.

Deal with scripts first

Scripts are easier and safer to fix than CSS. Every script that is not needed to render the first screen should have defer:

<script src="/app.js" defer></script>
<script src="https://third-party.example/tag.js" async></script>

Then look at what is left. Analytics, chat, A/B testing and tag managers rarely need to run before the page is visible, and a tag manager in particular is a script whose whole job is to load more scripts — deferring it defers everything inside it. Watch out for anti-flicker snippets from A/B tools, which deliberately hide the page until they load; that is a blocking file with extra steps.

Then the stylesheets

Split critical from the rest

Inline the styles needed for the first viewport in a <style> block, and load the full stylesheet without blocking:

<style>/* critical styles for the first screen */</style>
<link rel="stylesheet" href="/full.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/full.css"></noscript>

The media="print" trick works because the browser downloads print stylesheets at low priority without blocking rendering, and the onload switches it to apply once it has arrived. Keep the inlined part small — if it is more than about 10 KB you have inlined too much.

Scope stylesheets you only sometimes need

A stylesheet with a media attribute that does not match the current device is downloaded but does not block. Splitting print styles or wide-viewport styles out is free.

Delete what is not used

Run DevTools’ Coverage panel on your key pages. Themes and page builders routinely ship a stylesheet covering every feature in the product, of which one page uses four percent. Removing unused CSS shrinks the file that is blocking you in the first place.

Fonts count too

A font declared with the default font-display: auto hides text for up to three seconds while it loads. Set swap, preload only the one or two files used above the fold, and self-host so you are not paying for a connection to another domain before the font download can even start.

Measure before and after, on the field

This is an area where the lab score moves easily and real users sometimes do not — you can defer a script into a place where it still blocks the interaction that matters, and the audit goes green while your INP gets worse. Re-run the check afterwards and look at First Contentful Paint and LCP, not at the audit list.

Common questions

What makes a file render-blocking?
A stylesheet in the head blocks rendering until it downloads and parses, because the browser refuses to paint content it might have to restyle. A script without defer or async blocks HTML parsing at the point it appears, because it might document.write something. Both stop the page appearing.
What is the difference between defer and async?
async runs the script as soon as it downloads, interrupting parsing whenever that happens, and order is not guaranteed. defer waits until the HTML is fully parsed and runs scripts in document order. For almost everything you control, defer is the right choice; async suits independent third-party tags that do not depend on anything.
Is inlining CSS always better?
No. Inlined CSS cannot be cached separately, so it is re-sent with every page. Inline only the small amount needed to render the first viewport — a few kilobytes — and load the rest normally. Inlining a 200 KB stylesheet makes the first paint worse, not better.
My tool says I have 12 render-blocking files. Do I need to fix all of them?
No. Sort by how long each one actually blocks for. Two or three usually account for nearly all of it, and the rest are small files whose removal changes nothing measurable.

Check a page against this

Free, no signup, no ads. We keep nothing except the shareable result, for 30 days.

Enter any public URL. You’ll get the one change that recovers the most load time, what it’s worth, and the measurements underneath.

Other guides