Render-blocking resources are scripts and stylesheets in the <head> that the browser must download and process before it can paint anything on screen. Until they arrive, visitors stare at a blank page. Lighthouse reports them in the Render-blocking requests insight, formerly the Eliminate render-blocking resources audit. The fix is to load only what the first paint truly needs, and defer, inline or remove the rest.
What makes a resource render-blocking
The browser builds the page top to bottom. When it meets these in the <head>, it stops rendering until they are done:
- Classic scripts without
async,deferortype="module":
<script src="/analytics.js"></script>
- Stylesheets that apply to the current screen:
<link rel="stylesheet" href="/styles.css">
- Font stylesheets from third parties, which add another server to connect to before text can render.
Stylesheets block on purpose: without them the page would flash unstyled. Scripts block because they might change the page before it is shown. Most scripts never need that power.
Why it matters
- First Contentful Paint and Largest Contentful Paint get slower, because nothing paints until the blocking requests finish. LCP is one of the Core Web Vitals, which feed into ranking.
- Slow connections suffer most. Every blocking file is a round trip, and on mobile networks round trips are expensive.
- Visitors leave. A blank screen is the moment people hit the back button, and a back button click is a lost visitor you already paid for.
How to find render-blocking resources
- Lighthouse or PageSpeed Insights. Run a report and open the Render-blocking requests insight. It lists each file and the estimated time you would save.
- Chrome DevTools. In the Network panel, the render-blocking column (or the request's priority and timing) shows which files delay first paint. The Performance panel shows how long the page stays blank.
- Every page, every day. UpCrawler counts blocking scripts and stylesheets in the
<head>of each crawled page and flags Render-blocking resources, so a new tag added by marketing on Tuesday shows up before it drags your Core Web Vitals down.
How to fix it
Defer scripts that do not affect the first paint
<script src="/app.js" defer></script>
<script src="/analytics.js" async></script>
deferdownloads in parallel and runs after the HTML is parsed, in order. Use it for most scripts.asyncdownloads in parallel and runs as soon as it arrives, in any order. Use it for independent scripts such as analytics.type="module"scripts are deferred by default.
Inline critical CSS, load the rest later
Put the small amount of CSS needed for the first screen directly in a <style> tag, and load the full stylesheet without blocking:
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>
For CSS that only applies in some contexts, split it into its own file and let the media attribute tell the browser it does not need to wait:
<link rel="stylesheet" href="/print.css" media="print">
Inlining critical CSS is an advanced optimisation that can cause styling bugs, so measure before and after, and start by minifying and removing unused CSS.
Load fonts without blocking text
Self-host fonts where possible, and use font-display: swap so text renders immediately in a fallback font and swaps when the web font arrives.
Remove what you do not use
The fastest resource is the one you delete. Old A/B testing snippets, unused icon fonts and tags for tools nobody logs into anymore are common culprits. Offscreen images compete for the same bandwidth, so lazy load them as well.
Fixing it on your platform
Next.js bundles and optimises your CSS automatically, and next/font self-hosts fonts without a blocking third-party request. For third-party scripts, use next/script with a loading strategy instead of a raw <script> tag:
import Script from 'next/script'
<Script src="https://example.com/widget.js" strategy="lazyOnload" />
afterInteractive (the default) loads early but after some hydration, and lazyOnload waits until the browser is idle. Keep beforeInteractive for the rare script that must run before the page hydrates, placed in the root layout, since it delays everything else.
Themes and plugins often enqueue scripts in the header. Since WordPress 6.3, scripts you enqueue yourself can be deferred without a plugin:
wp_enqueue_script( 'chat-widget', get_theme_file_uri( 'js/chat.js' ), [], null, [ 'strategy' => 'defer' ] );
For third-party plugins, performance plugins such as WP Rocket, Autoptimize or LiteSpeed Cache can defer JavaScript and generate critical CSS. Then deactivate plugins you no longer use, because each one can add its own scripts and styles to every page.
App scripts are the usual cause. Remove apps you no longer use, since some leave code in theme.liquid after uninstalling. For scripts you add yourself, add defer, and prefer themes built on Shopify's Online Store 2.0 architecture, which load most app code through app blocks and embeds instead of the <head>.
Let AI fix it, page by page.
Paste this prompt into AI with your project open. In UpCrawler, every affected page comes with a prompt like this, already filled in with its URL.
Defer or async every non-critical script, inline the critical CSS and load the rest asynchronously. Keep only what first paint genuinely needs in <head>.
Frequently asked questions
Can I remove all render-blocking resources?
Rarely, and you should not try. Some CSS has to block to avoid a flash of unstyled content. The goal is that only the CSS needed for the first screen blocks, and no scripts do.
Does async or defer break my scripts?
Scripts that depend on each other can break with async because it does not keep order. Use defer when order matters. Test after the change, especially scripts that write to the page with document.write.
Will fixing this improve my rankings?
It improves how fast your page appears, which helps Core Web Vitals and keeps more visitors on the page. Core Web Vitals feed into ranking but are one factor among many, so the biggest win is usually fewer people leaving before the page loads.
Share it with whoever runs your site’s SEO.