Render-blocking resources checker

Find every stylesheet and synchronous script that stops the browser from painting, see when the last one finishes, and fix them in order.

Why these files delay the first paint

Here is a small page with three resources in its <head>. Change how each one is loaded and watch the orange first-paint line move. Timings assume a 70 ms round trip.

main.css (40 KB)
fonts.example.net/css
vendor.js (120 KB)
  • connection setup
  • download
  • parse / execute
  • orange name = render-blocking

576 ms (started at 576 ms)

The synchronous script is the longest pole: the parser stops at it, downloads 120 KB and executes it before it will build the rest of the page.

How to eliminate render-blocking resources

JavaScript

  • <script defer src="app.js"> — downloads in parallel, runs in order after the HTML is parsed. The right default for your own code.
  • <script async src="tag.js"> — runs whenever it arrives, in any order. Fine for independent analytics tags.
  • type="module" scripts are deferred automatically.

CSS

  • Inline critical CSS. Put the rules needed for the first screen (often under 14 KB so it fits in the first round trip) in a <style> tag, and load the full sheet without blocking.
  • Split by media. <link rel="stylesheet" href="print.css" media="print"> never blocks screen rendering.
  • Avoid @import inside CSS — it creates a chain the browser can't discover until the first file arrives.
  • Self-host web-font CSS, or at least add <link rel="preconnect" href="https://fonts.example.net" crossorigin> so the connection setup overlaps the HTML download. Use font-display: swap so text shows in a fallback font meanwhile.

Preload vs prefetch

rel="preload" fetches something the current page needs soon, at high priority (a hero image, a font referenced deep in CSS). rel="prefetch" fetches something a future navigation might need, at idle priority. rel="preconnect" only opens the connection. None of them make a file non-blocking by themselves — they only move its download earlier.

Render-blocking time shows up directly in First Contentful Paint and LCP. To see the rest of your page's requests, run the full speed test.

Questions developers ask

What counts as a render-blocking resource?

A stylesheet linked in the <head> (unless its media query does not match, like media="print"), and a classic <script src> in the <head> without async, defer or type="module". The browser will not paint any content until these are downloaded and processed. Chrome also marks such requests with renderBlocking: "blocking" in its resource timing data.

How do I eliminate render-blocking resources?

For scripts: add defer (keeps order, runs after parsing) or async (runs as soon as it arrives), or move them to the end of <body>. For CSS: inline the small amount needed for the first screen and load the full stylesheet without blocking, split CSS by media query, and self-host third-party font CSS or preconnect to its origin.

Should I defer all JavaScript?

Almost always, yes. The exceptions are tiny scripts that must run before first paint, such as setting a dark-mode class to avoid a flash. Keep those inline and small. Anti-flicker snippets from A/B-testing tools deliberately block rendering — measure what they cost.

Is CSS always render-blocking?

Stylesheets whose media attribute matches the current device block rendering. A stylesheet with media="print" is still downloaded but at low priority and does not block. That is the basis of the common trick of loading with media="print" and switching to "all" in an onload handler.

How accurate is this checker?

It reads the HTML your server returns and applies the same rules the browser does to <link> and <script> tags in the <head>, including @import chains inside blocking CSS. It does not run JavaScript, so tags injected at runtime are not seen. Chrome's Lighthouse "Render-blocking requests" insight uses real rendering and can be used to confirm.