/ โ† Page Speed Fixes / Render-Blocking Resources
In this guide
  1. What counts as render-blocking, and what does not
  2. Why a few small files can cost seconds
  3. Triage: reading the report and the waterfall
  4. Choosing the fix for each blocking file
  5. The fix, step by step
  6. Resource hints and early hints, used carefully
  7. Platform notes
  8. Edge cases and trade-offs
  9. Stopping blockers from creeping back
  10. Questions and answers

What counts as render-blocking, and what does not

Browsers try to show something as soon as they can, but they will not paint until they have the styles that apply to the page and have run any script that might change the page before it is shown. Anything that the browser must fetch and process before that first paint is on the critical rendering path. Files on that path are what speed tools call render-blocking.

The label gets applied loosely, so it helps to know exactly which kinds of file block and which only look as if they do.

ResourceBlocks first paint?Notes
<link rel="stylesheet"> in the head with no media or a matching oneYesThe browser waits so it does not show unstyled content.
Stylesheet with a non-matching media value, such as printNoStill downloaded, at low priority.
A file pulled in by @import inside a blocking stylesheetYesFound late, so it adds a second round trip.
Classic <script src> in the head without defer or asyncYesStops the HTML parser until downloaded and run.
Script with defer, async or type="module"NoDownloads in parallel and runs later.
Web font CSS from a font serviceYesIt is a stylesheet, often on another host.
The font files themselvesNot the paintThey can hide text for a while, which is a separate problem.
Images, video, iframesNoThey slow LCP and use bandwidth but do not stop the first paint.
Inline <style> and inline <script>No extra requestThey still cost parsing time, and a large inline script still runs before paint.

Chromium-based browsers also support an explicit blocking="render" attribute, which lets a page deliberately make a script or style block. You will rarely want it, but if you see it in a template, it is doing exactly what it says.

๐Ÿ’ก A script placed at the very end of the body is parser-blocking but usually not render-blocking in practice, because the browser can paint the content above it first. Speed tools may still flag it if it sits in the head of a theme you did not write, so always check where the tag really is.

Why a few small files can cost seconds

People are often surprised that a 10 KB stylesheet appears near the top of the report. File size is only one part of the cost. Before a blocking file can be used, the browser may need to:

  1. Look up the host name if the file is on a domain the page has not used yet.
  2. Open a connection, which on HTTPS means a TCP handshake and a TLS negotiation, or a QUIC handshake on HTTP/3.
  3. Wait for the server to respond, which for a third-party service is outside your control.
  4. Download the bytes, competing for bandwidth with every other file in flight.
  5. Parse and apply it, or in the case of a script, compile and run it on the main thread.

On a fast office connection all of that happens in a blink. On a phone with a weak mobile signal, each round trip can be long, and the steps for a new host happen one after another. That is why a single font stylesheet on a separate domain can hold the first paint back further than a larger stylesheet on your own domain that reuses the existing connection.

Chains multiply the delay

The worst case is a chain: a blocking file that, once loaded, asks for another blocking file. A stylesheet that imports a second stylesheet, which then imports a font service's CSS, makes the browser wait for three sequential trips before it can paint. Lighthouse used to show these as "critical request chains", and newer versions fold the same idea into its network dependency insight. The analyzer's waterfall shows them as bars that start only when the previous bar finishes.

Scripts add processing time

A blocking script is expensive twice over. The HTML parser stops while it downloads, and then the main thread is busy while it runs. A large library in the head can therefore cost more after it arrives than it took to download, especially on mid-range phones.

Triage: reading the report and the waterfall

Start by running the Page Speed Analyzer on each main template. It measures the page with real-user and lab data and names the requests and files holding it back, and its network waterfall shows the order in which they load. Look for the requests that finish before the first paint marker; those are your candidates.

Cross-check with Lighthouse

PageSpeed Insights and Lighthouse list render-blocking files with a transfer size and an estimated saving. Recent versions show this as a render-blocking requests insight; older versions call it "Eliminate render-blocking resources". The savings figure is modelled, so use it to rank files, not as a promise.

Confirm in DevTools

  1. Open the Performance panel, turn on network and CPU throttling, and record a reload.
  2. In the network track, select each early request. The summary shows whether Chrome treated it as render-blocking.
  3. Find the FCP marker on the timings track. Everything blocking that ends just before it is holding up the paint.

To get a quick list of everything that finished before first paint, you can run this in the Console after a fresh, uncached load:

const fcp = performance.getEntriesByName('first-contentful-paint')[0].startTime;
performance.getEntriesByType('resource')
  .filter(r => r.responseEnd < fcp && /css|script|link/.test(r.initiatorType))
  .map(r => ({ file: r.name.split('?')[0], host: new URL(r.name).host,
               ms: Math.round(r.responseEnd - r.startTime) }));

This lists requests that finished before the first paint. Not every one of them blocked it, but every blocker will be in the list, and the host column shows at a glance which ones need a new connection.

Use a filmstrip

A filmstrip from WebPageTest, or the screenshots strip in the DevTools Performance panel, shows the moment something first appears on screen. That moment, often called start render, is what visitors feel. Keep the filmstrip; you will compare against it at the end.

โš ๏ธ Always test uncached and throttled. On a repeat visit, stylesheets and scripts often come from the browser cache and the blocking cost disappears, which hides the problem that first-time visitors from search actually hit.

Choosing the fix for each blocking file

Once you have the list, every blocking file falls into one of a few groups. The right fix depends on the group, not on how large the file is.

What the file isFirst questionUsual fixDetailed guide
Your main stylesheetHow much of it does the first screen need?Inline the critical rules, load the rest without blockingRender-blocking CSS
A plugin, app or widget stylesheetIs the feature on this page at all?Load it only on pages that use itRender-blocking CSS
Font service CSSCould the fonts be served from your own domain?Self-host, or preconnect and trim the families and weights requestedThis page, steps 4 and 5
Your own script in the headDoes anything need it before the page is shown?Add defer, or move it out of the headRender-blocking JavaScript
A third-party script in the headWho asked for it, and is it still used?Remove it, or load it with async or after loadThird-party scripts
A very large stylesheet or bundleWhy is it so large?Split, purge unused rules or codeHeavy CSS, JS bundles

This guide handles the parts that apply across all of them: removing what is not needed, cutting connection time and breaking chains. The two linked guides for CSS and JavaScript cover the file-level techniques, such as generating critical CSS or choosing between defer and async, in full.

The fix, step by step

Step 1

Record a baseline with a filmstrip

Pick your busiest templates, such as the home page, a service or product page and an article, and test each one on a throttled mobile profile with the cache disabled. Save the analyzer result, the Lighthouse list of blocking files and a filmstrip showing when content first appears. Write down the start render time and First Contentful Paint for each template. Without this record you cannot tell later whether a change helped, made no difference or quietly made the page worse.

Step 2

List each blocker with its type, host and owner

Build a simple table with one row per blocking file. Note whether it is a stylesheet, a script or font CSS, which host it comes from, its size and roughly how long it took. Then add an owner column: the theme, a named plugin or app, your developer, a marketing tag or a font service. The owner column matters most, because it tells you who can change the file and who must agree before anything is removed.

Step 3

Delete blockers that nothing on the page uses

Go through the table and ask of each file whether the page would look or behave differently without it. Old slider libraries, icon sets for a single icon, a second copy of jQuery, a widget from a trial that ended and a stylesheet for a form that only appears on the contact page are common finds. Remove them from the templates, or restrict them to the pages that genuinely use them. Removing a blocker is always faster than optimising it.

Step 4

Cut the connection cost for other hosts

For each blocking file on another host, decide whether it can move to your own domain. Font files and small libraries usually can, and self-hosting removes a lookup, a handshake and a separate server from the critical path. Where a file must stay on its host, add <link rel="preconnect"> for that origin near the top of the head, using the crossorigin attribute for fonts. Keep preconnects to the two or three hosts that matter, because each one opens a real connection.

Step 5

Break request chains so blockers are found early

Look for any blocking file that only starts downloading after another one finishes. Replace @import rules with direct <link> tags or combine the files at build time. If a font service stylesheet is loaded from inside your main stylesheet, move its link into the HTML head. If a script in the head injects another blocking script, reference the second file directly. The aim is for every file the first paint needs to be visible in the HTML itself.

Step 6

Choose the delivery fix for each remaining file

What is left should be files the page genuinely needs. For your main stylesheet, inline the small set of rules the first screen uses and load the full file without blocking. For scripts, add defer unless something truly must run before the page is shown. For third-party tags, load them asynchronously or after the page has rendered. Make one change at a time on a staging copy, and check the page still looks and works right after each change.

Step 7

Retest and compare start render, not just the score

Run the same tests with the same settings you used for the baseline and put the filmstrips side by side. The number that matters most here is when content first appears on screen, followed by First Contentful Paint and Largest Contentful Paint. The Lighthouse score can move for unrelated reasons, so do not judge the work on it alone. After the change has been live for a few weeks, check real-user data to confirm visitors see the same improvement.

Resource hints and early hints, used carefully

Some blocking files cannot be avoided: most sites need at least a small stylesheet before the first paint. For those, the goal is to start the download as early as possible.

preconnect

preconnect tells the browser to open a connection to another host before it finds a file there. It helps when a blocking file must stay on a separate domain. It wastes effort if the host is not used early, and browsers close unused connections after a short time.

<link rel="preconnect" href="https://fonts.example-cdn.com" crossorigin>

preload

preload fetches a specific file early at high priority. It is useful for a blocking file the browser would otherwise find late, such as a font referenced from CSS or a stylesheet requested by a script. It does not make a blocking file non-blocking, and preloading several large files can push back the ones that matter. Treat each preload as a decision you can justify.

103 Early Hints

Some servers and CDNs can send an informational 103 Early Hints response while the page itself is still being generated. It can carry preconnect and preload links, so the browser starts on your critical stylesheet before the HTML arrives. Support is strongest in Chromium-based browsers, and it helps most when the server takes a while to build pages. Check your host or CDN documentation for whether it is available and how to switch it on.

โš ๏ธ HTTP/2 Server Push, which was once recommended for the same purpose, has been removed from Chrome and should not be used. Early hints and preload are the current approaches.

Platform notes

WordPress

Blockers usually come from the theme and from plugins that enqueue their styles and scripts on every page. Optimisation plugins can defer scripts, inline critical CSS and combine files, but switch features on one at a time and check menus, forms and sliders after each. Asset manager plugins, or a few lines in your child theme, can stop a plugin loading its files on pages where it is not used. The WordPress speed guide covers this in more depth.

Shopify

You cannot edit the scripts Shopify injects through content_for_header, but you control the theme's own tags, and many blockers are app code left in theme.liquid. Duplicate the theme before editing. The Shopify speed guide covers app code and theme weight.

Custom and static sites

You have full control, so the fixes are direct edits to the head template. Build tools can generate critical CSS and add hashes to file names so full stylesheets can be cached for a long time.

Frameworks

Next.js, Nuxt, Astro and similar frameworks generally load their own scripts without blocking and can inline critical CSS. The blockers that remain are usually global stylesheets, font imports and third-party scripts added by hand to the root layout. The Next.js speed guide covers framework-specific options.

Edge cases and trade-offs

Stopping blockers from creeping back

Render-blocking files return whenever someone installs a plugin or app, pastes a tag into the head, or a theme update changes how assets load. A few habits keep the critical path short:

For more background on how speed fits together, the Page Speed Analyzer guide explains the reports, and the LCP guide shows how render-blocking time feeds into the main content element's load time.

Questions and answers

1. What does eliminate render-blocking resources actually mean?

It means the page links files, usually stylesheets and scripts in the head, that the browser must download and process before it can draw anything. Until they arrive, visitors see a blank screen. Eliminating them rarely means deleting every one. It means removing the ones the page does not need, loading scripts so they do not stop the parser, and keeping only a small amount of essential CSS on the critical path so the first screen can appear quickly.

2. Are images render-blocking?

No. Images do not stop the browser from painting the rest of the page. They can still slow down Largest Contentful Paint if the main image is large, discovered late or lazy-loaded, and they compete for bandwidth with blocking files early in the load. So images matter for speed, but they belong to a different part of the problem. If a report lists images as blocking, check the tool, because it is probably describing something else, such as LCP delay.

3. Why does my font stylesheet show up as render-blocking?

A font service usually gives you a link to a stylesheet that describes the font files. That stylesheet is a normal CSS file linked in the head, so the browser waits for it before painting. It is often on a separate domain, which adds a lookup and a new connection before any bytes arrive. Self-hosting the font files and their small CSS on your own domain removes that delay. If you keep the service, add a preconnect hint and request fewer weights.

4. Is it safe to defer every script on my site?

Not blindly. Deferring changes when a script runs, and code that expects a library to be available straight away can break, for example an inline snippet that calls jQuery before the deferred copy has loaded. Menus, sliders, forms and checkout flows are where problems show up. Defer scripts one at a time on a staging copy, test the pages that use them, and keep any script that genuinely has to run first as small as possible.

5. Will removing render-blocking resources improve my Core Web Vitals?

It usually helps First Contentful Paint and often Largest Contentful Paint, because both depend on how soon the browser can start painting. Whether it moves your Core Web Vitals assessment depends on what else is slow. If your server responds slowly or your main image is huge, those may still dominate. Real-user data takes time to update, since it reflects visits over roughly the previous 28 days, so allow a few weeks before judging the change.

6. Why does the report still show render-blocking files after I fixed them?

There are a few common reasons. A cache or CDN may still be serving the old HTML, so purge it and retest. An optimisation plugin may only apply its changes to visitors who are not logged in, so test in a private window. Some files are legitimately blocking, such as a small critical stylesheet, and tools will keep listing them. Finally, check the source of the flagged file: it may be injected by a platform or app you did not edit.

7. Should I use preload for all my CSS and JavaScript files?

No. Preload raises the priority of a file so the browser fetches it early, which helps a small number of critical files that would otherwise be found late. If you preload many files, they all compete for the same bandwidth and the important ones arrive later, not sooner. Preload also does not stop a stylesheet from blocking the paint. Use it for one or two files you can clearly justify, and check the waterfall afterwards to confirm it helped.

See what is holding up your first paint

The Page Speed Analyzer measures your page with real-user and lab data, shows the network waterfall, and names the specific files and scripts holding the page back, so you can see which blockers to deal with first.

Open Page Speed Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All Page Speed Fixes  ·  Render-Blocking CSS  ·  Render-Blocking JavaScript  ·  Fixing Slow LCP  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.