SSL Checker DMARC Meta Tags Site Speed Broken Links AI Chat Bookings Try ModusOp

Published 27 April 2026

When the browser parses HTML and encounters certain resources — most CSS files and synchronous JavaScript — it has to stop and download them before continuing. This is called "render-blocking", and it's one of the largest controllable factors in how fast a page first paints. A single render-blocking script in the head can add 500-1500ms to LCP.

Modern frameworks and CDNs have made this much easier to handle than it was a decade ago, but the patterns that cause render-blocking still recur — especially around third-party scripts, web fonts, and "we'll just include a CSS file in the head" templates.

What Counts as Render-Blocking

The browser blocks rendering on:

The browser does NOT block rendering on:

Async vs Defer

Two attributes that change script loading behaviour:

async

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

Downloads in parallel with HTML parsing. Executes as soon as it's downloaded, even if the rest of the HTML hasn't been parsed yet — which means the script can run before the DOM is fully ready, and order between multiple async scripts is not guaranteed.

Use for independent scripts that don't depend on the DOM or each other: analytics pixels, third-party widgets, social embeds.

defer

<script src="app.js" defer></script>

Downloads in parallel with HTML parsing. Executes after HTML is fully parsed but before DOMContentLoaded. Multiple defer scripts execute in the order they appear in the HTML.

Use for application logic that needs the DOM or has dependencies between scripts: framework code, page initialisation, anything you used to put at the end of the body.

Modules

<script src="app.js" type="module"></script>

ES modules are deferred by default — same behaviour as defer without needing to specify it.

The Default Should Be Deferred

For most scripts, the right answer is defer:

<script src="/dist/app.js" defer></script>

Let the browser parse the HTML in parallel. Run the script after parsing. This single change eliminates most render-blocking on most sites.

Common pushback: "but my script needs to run before the page is interactive." It will — defer scripts run before DOMContentLoaded, which is the standard signal for "page is ready". Unless you have a specific reason to block rendering, defer is right.

CSS: Critical and Non-Critical

CSS is render-blocking by default. The browser won't paint the page until all stylesheets in the head have loaded, because it doesn't know which styles affect what's visible.

The technique to unblock CSS is "critical CSS":

  1. Identify the CSS needed for above-the-fold content — typically 5-15KB of styles for the header, hero, and visible navigation.
  2. Inline that CSS in the head as a <style> block.
  3. Load the rest of your CSS asynchronously, typically with the print-trick:
<link rel="stylesheet" href="/main.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/main.css"></noscript>

The browser doesn't block rendering on print stylesheets. Once the file loads, JavaScript flips the media to "all" and the styles apply.

For frameworks: Next.js, Nuxt, SvelteKit, and Astro extract critical CSS automatically. WordPress sites can use a critical CSS plugin or service like Critical or critters. Manual extraction is a pain; use tooling.

Web Fonts and Render-Blocking

Web fonts are tricky. The CSS that defines them isn't render-blocking, but the font files themselves block text render until they load (or until the browser's "font-display timeout" expires).

Mitigations:

Third-Party Scripts: The Quiet Killers

The render-blocking that matters most isn't usually your own code — it's the third-party scripts you've added over years:

Each one, individually, is "small". Together they're often 1-2MB of script downloaded and executed on every page load. Fixes:

Identification

Several tools surface render-blocking resources:

The Practical Sequence

  1. Audit third-party scripts. Remove what you don't need; defer what you do.
  2. Add defer to your own scripts in the head.
  3. Inline critical CSS; async-load the rest.
  4. Add font-display: swap to web fonts.
  5. Preload critical fonts and the LCP image.
  6. Re-test with Site Speed Check.

Each step independently improves first paint. Done together, the impact compounds — sites that were taking 3-5 seconds to first paint can drop to under 1 second after a focused render-blocking audit.

What Doesn't Need to Be Optimised

The HTML itself. The image and video files. Async scripts. Properly deferred scripts. Print stylesheets. Anything below the fold. The browser handles all of these efficiently without intervention.

The 80/20 of render-blocking optimisation is: defer your scripts, extract critical CSS, audit your third-party junk. Three changes, often visible improvement within a day. Site Speed Check measures the before and after.

Find your render-blocking resources

Site Speed Check identifies every render-blocking CSS and JS file and reports how much each delays your first paint.

Run a Speed Test →