Render-Blocking Resources

Written by Backbone Tutorials Team

Last updated: June 2026 · 9 min read

Open Chrome DevTools on a slow-loading page, switch to the Performance panel, and record a load. The waterfall almost always tells the same story: a handful of resources at the top of the network tab are holding everything below them hostage. Nothing paints until those files arrive. Those are render-blocking resources, and eliminating them is one of the highest-leverage moves in frontend performance work.

This guide builds on the browser rendering pipeline explanation of the critical path and connects to the loading strategy in progressive rendering.

Render-blocking vs non-blocking resource loading Blocking: CSS and sync script hold up first paint. Non-blocking: deferred script and inlined critical CSS allow early paint. Time → Blocking Fixed HTML CSS (blocking) Sync script (blocking) Paint blocked until here HTML + inline CSS defer script (background) Paint early paint
Blocking CSS and synchronous scripts delay first paint until they finish. Inlining critical CSS and deferring scripts move paint to just after the HTML arrives.

What makes a resource blocking

Not every resource that loads before paint is render-blocking. The distinction is whether the browser is willing to show anything without it.

The browser's rule

A render-blocking resource is one the browser refuses to paint before. Stylesheets in the <head> always qualify: the browser needs the CSSOM complete before it can build the render tree and compute layout. Synchronous <script> tags without defer or async are both parser-blocking and render-blocking: the HTML parser stops, the script downloads and runs, then parsing resumes. Images, fonts, and deferred scripts do not block rendering; they either load in parallel or load on demand. The critical path is everything on the blocking list between the first byte of HTML and the first paint.

CSS and the CSSOM

CSS is render-blocking by design. Understanding why makes the solutions obvious.

Why the browser waits for stylesheets

<!-- Both of these block rendering until downloaded -->
<link rel="stylesheet" href="/styles/main.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter">

<!-- This does NOT block: media hint tells browser it is print-only -->
<link rel="stylesheet" href="/styles/print.css" media="print">

Serving a page before its styles arrive produces a flash of unstyled content, so the browser waits. Any stylesheet in the head without a media attribute is assumed to apply immediately and blocks paint. A media="print" or media="(min-width: 1200px)" attribute tells the browser the sheet is conditional and lets it download non-blocking. Third-party font stylesheets are a common hidden blocker: the Google Fonts <link> is a stylesheet that blocks rendering until it resolves, which is why self-hosting Inter with a local @font-face is one of the Lighthouse 100 recommendations in the frontend performance guide.

Scripts and parser blocking

A synchronous script is even more disruptive than a stylesheet because it halts both parsing and rendering.

defer vs async vs inline

<!-- Blocks parser + render until downloaded and executed -->
<script src="app.js"></script>

<!-- Downloads in parallel; runs after DOM is parsed; order preserved -->
<script src="app.js" defer></script>

<!-- Downloads in parallel; runs as soon as ready; order not preserved -->
<script src="analytics.js" async></script>

For application bundles, defer is almost always the right choice: it keeps the parser running, preserves execution order across multiple scripts, and runs after the DOM is complete. async suits independent third-party scripts where execution order does not matter. Inline scripts in the head without a type="module" or defer equivalent block immediately, so keep them tiny or move them to the body end.

Inlining critical CSS

The fastest stylesheet is one that is already in the document, requiring no additional network round trip.

Extract, inline, and load the rest asynchronously

<!-- In the head: inline only above-the-fold styles -->
<style>
  body { font-family: Inter, sans-serif; margin: 0; }
  .nav { background: #111827; }
  .hero { max-width: 900px; margin: 0 auto; }
</style>

<!-- Load full stylesheet non-blocking after paint -->
<link rel="preload" href="/styles/main.css" as="style"
      onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles/main.css"></noscript>

Tools like Critical, PurgeCSS, or a build step can extract the above-the-fold CSS automatically. The inline styles satisfy the CSSOM requirement for the first paint. The full stylesheet loads via rel="preload" which fetches at high priority without blocking render, then the onload callback switches it to a real stylesheet. This pattern, combined with defer on the JavaScript bundle, removes all render-blocking resources from the critical path.

Preload and resource hints

Sometimes eliminating blocking is not possible, but you can reduce its cost by fetching the resource earlier.

Preload, preconnect, and dns-prefetch

<!-- Start fetching the hero image early in the head -->
<link rel="preload" href="/assets/hero.webp"
      as="image" fetchpriority="high">

<!-- Open the TCP connection to a third-party origin early -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<!-- Resolve DNS only, lower overhead than preconnect -->
<link rel="dns-prefetch" href="https://analytics.example.com">

rel="preload" tells the browser to fetch a resource at high priority as soon as the HTML is parsed, before the browser's own preload scanner would normally find it. Use it for the LCP image, the critical font, or any resource the browser discovers late in the document. preconnect opens the TCP and TLS handshake to a third-party origin ahead of time, saving a round trip when the actual request fires. Do not preload everything: over-preloading competes with the resources that actually matter and can make LCP worse.

Measuring and auditing

Identifying blocking resources precisely is a job for tools, not guesswork. The fixes above only help once you know exactly what is blocking.

Lighthouse, WebPageTest, and DevTools

Lighthouse's "Eliminate render-blocking resources" audit lists every blocking stylesheet and script with an estimated savings in milliseconds. The Performance panel in Chrome DevTools shows the waterfall and highlights the render-blocking period in red before the first paint marker. WebPageTest provides a filmstrip view that shows exactly when pixels first appear. Run all three on a cold load with a throttled connection, because render blocking is most painful on slow networks where the download time for each file is measured in hundreds of milliseconds rather than single digits. Once you have eliminated the blocking resources for your page, the next guide examines what the DOM itself costs once rendering begins.

Frequently Asked Questions

What is a render-blocking resource?

A render-blocking resource is a file the browser must download and process before it can paint anything to the screen. Stylesheet link tags in the head are always render-blocking. Script tags without defer or async are both parser-blocking and render-blocking.

Why does CSS block rendering?

The browser needs the CSSOM to build the render tree, so it cannot paint until every stylesheet in the head is downloaded and parsed. Serving an incomplete render would cause a flash of unstyled content, which is why CSS blocks by design.

What is critical CSS?

Critical CSS is the minimal set of styles needed to render the above-the-fold content. Inlining it in a style tag in the head lets the browser paint the visible viewport immediately without waiting for an external stylesheet to download.

Does defer remove render blocking for scripts?

Yes. A script with defer downloads in parallel with HTML parsing and executes after parsing is complete, so it neither blocks the parser nor delays the first paint. The async attribute also avoids blocking parsing but executes as soon as the script downloads, which can still delay interactive content if it runs at an inopportune moment.

Read next: the Rendering hub, or continue to progressive rendering for the delivery strategies that work alongside a clean critical path.

See a lean critical path in practice.

The Backbone guide is built with minimal blocking resources and inline critical CSS.

Explore the Backbone Guide →