Guideintermediate

How to Eliminate Render-Blocking Resources for Faster Pages

A practical guide to identifying and removing render-blocking CSS and JavaScript that slows down your site. Covers async loading, critical CSS, and font optimization.

Rankwise Team·Updated Mar 16, 2026·6 min read

Render-blocking resources are CSS files, JavaScript files, and fonts that prevent the browser from painting content to the screen until they've fully loaded and been processed. Eliminating them is one of the highest-impact performance optimizations you can make.


What Are Render-Blocking Resources?

When a browser loads a page, it parses the HTML from top to bottom. When it encounters a <link> to a stylesheet or a <script> tag (without async or defer), it pauses rendering until that resource downloads and executes. Nothing appears on screen until these blocking resources finish.

Default blocking behavior:

Resource TypeBlocking by Default?Impact
CSS (<link rel="stylesheet">)YesBlocks all rendering
JS (<script>)YesBlocks parsing and rendering
JS (<script defer>)NoDownloads in parallel, executes after HTML parsing
JS (<script async>)NoDownloads in parallel, executes when ready
FontsPartiallyCan delay text paint (FOIT/FOUT)

The more render-blocking resources in your <head>, the longer users stare at a blank screen.


Identifying Render-Blocking Resources

Using Lighthouse

Run a Lighthouse audit (Chrome DevTools → Lighthouse tab). Look for the "Eliminate render-blocking resources" opportunity. It lists every resource blocking the first paint and the potential time savings.

Using the Performance Panel

  1. Open Chrome DevTools → Performance tab
  2. Record a page load
  3. Look at the waterfall chart for the first ~2 seconds
  4. Identify CSS and JS requests that complete before First Contentful Paint (FCP)
  5. These are your render-blocking resources

Using WebPageTest

Run a test at webpagetest.org and examine the waterfall view. Render-blocking resources appear as bars that extend before the "Start Render" marker.


Eliminating Render-Blocking CSS

CSS is the most common render blocker. The browser won't paint anything until it has processed all CSS linked in the <head>. Here's how to fix that without breaking your styles.

Strategy 1: Inline Critical CSS

Extract the CSS needed for above-the-fold content and inline it directly in the HTML <head>. Load the full stylesheet asynchronously.

How it works:

<head>
  <!-- Critical CSS inlined -->
  <style>
    /* Only the CSS needed for above-fold content */
    body {
      font-family: system-ui;
      margin: 0;
    }
    .hero {
      padding: 4rem 2rem;
    }
    .nav {
      display: flex;
      height: 64px;
    }
  </style>

  <!-- Full stylesheet loaded async -->
  <link
    rel="preload"
    href="/styles.css"
    as="style"
    onload="this.onload=null;this.rel='stylesheet'"
  />
  <noscript><link rel="stylesheet" href="/styles.css" /></noscript>
</head>

Tools for extracting critical CSS:

  • Critical (npm package) — Extracts critical-path CSS automatically
  • Critters (Webpack/Vite plugin) — Inlines critical CSS during build
  • PurgeCSS — Removes unused CSS to reduce total size

Strategy 2: Split CSS by Route

Instead of one large stylesheet for the entire site, load only the CSS each page needs. Modern bundlers (Webpack, Vite, Next.js) handle this automatically when you use CSS modules or scoped styles.

Strategy 3: Media Query Splitting

Split print styles and large-breakpoint styles into separate files with media attributes. The browser still downloads them but won't block rendering for non-matching media.

<link rel="stylesheet" href="/main.css" />
<link rel="stylesheet" href="/print.css" media="print" />
<link rel="stylesheet" href="/large.css" media="(min-width: 1200px)" />

Eliminating Render-Blocking JavaScript

Use defer for Non-Critical Scripts

The defer attribute tells the browser to download the script in parallel with HTML parsing and execute it after the DOM is ready. Order is preserved.

<!-- Blocks rendering -->
<script src="/analytics.js"></script>

<!-- Non-blocking, executes after DOM ready -->
<script src="/analytics.js" defer></script>

Use defer for scripts that need the DOM but aren't needed for initial render: analytics, third-party widgets, below-fold interactivity.

Use async for Independent Scripts

The async attribute downloads the script in parallel and executes it as soon as it's ready, regardless of DOM state. Execution order is NOT guaranteed.

<script src="/tracking.js" async></script>

Use async for scripts that are independent and don't depend on DOM order: analytics pixels, ad scripts, performance monitoring.

Move Scripts to Bottom

If defer and async aren't options (legacy code), move <script> tags to the bottom of <body>. This ensures HTML content parses and renders before scripts execute.

Code-Split Large Bundles

A 500KB JavaScript bundle blocks the main thread for hundreds of milliseconds even after downloading. Split your code:

  • Route-based splitting — Load only the JS needed for the current page
  • Component-based splitting — Lazy-load heavy components (charts, editors, maps)
  • Dynamic importsimport() syntax for on-demand loading

Optimizing Font Loading

Web fonts cause either invisible text (FOIT) or a flash of unstyled text (FOUT). Both hurt perceived performance and can contribute to CLS.

Use font-display: swap

@font-face {
  font-family: "Custom Font";
  src: url("/fonts/custom.woff2") format("woff2");
  font-display: swap;
}

swap shows fallback text immediately and swaps to the custom font when loaded. Users see content instantly.

Preload Critical Fonts

<link
  rel="preload"
  href="/fonts/heading.woff2"
  as="font"
  type="font/woff2"
  crossorigin
/>

Preloading tells the browser to fetch the font early, reducing the time before the font swap happens.

Subset Your Fonts

Most sites use a small subset of characters. Subsetting removes unused glyphs:

  • Full Latin font: ~150KB
  • Subsetted to English characters: ~20KB

Tools: glyphhanger, FontSquirrel generator, Google Fonts (subsets automatically via &subset=latin)

Self-Host Fonts

Self-hosting fonts eliminates DNS lookups and connection setup to third-party font CDNs. Download fonts, convert to WOFF2, and serve from your own domain.


Measuring the Impact

After implementing changes, measure the improvement:

MetricBeforeAfterTarget
FCP (First Contentful Paint)< 1.8s
LCP (Largest Contentful Paint)< 2.5s
Total blocking time< 200ms
Render-blocking resources0

Run Lighthouse before and after. Use the Performance tab waterfall to verify resources are no longer blocking the render path.


Implementation Checklist

CSS:

  • Critical CSS inlined in <head>
  • Non-critical CSS loaded asynchronously
  • Unused CSS removed (PurgeCSS or equivalent)
  • Print and large-viewport styles split by media query

JavaScript:

  • All non-essential scripts use defer or async
  • Large bundles code-split by route
  • Heavy components lazy-loaded
  • Third-party scripts deferred or loaded on interaction

Fonts:

  • font-display: swap applied to all custom fonts
  • Critical fonts preloaded
  • Fonts subsetted to needed character sets
  • Using WOFF2 format

FAQs

Will removing render-blocking resources break my site?

Not if done correctly. The key is ensuring critical CSS (above-the-fold styles) is still available immediately. Moving non-critical CSS and JS to async loading shouldn't affect appearance or functionality.

How many render-blocking resources are normal?

Zero is the target. In practice, one small critical CSS file in the <head> is acceptable. Any JavaScript in the <head> without defer or async is a problem.

Does this affect SEO directly?

Yes. Render-blocking resources slow down FCP and LCP, both of which are Core Web Vitals that Google uses as ranking signals. Faster rendering also helps AI crawlers parse your content more efficiently.

Should I use async or defer for my scripts?

Use defer for scripts that depend on DOM order or other scripts. Use async for independent scripts that can run in any order. When in doubt, use defer—it's safer and more predictable.

Part of the SEO Fundamentals topic

Newsletter

Stay ahead of AI search

Weekly insights on GEO and content optimization.