/ โ† CSS Checker Fixes / Render-Blocking CSS
In this guide
  1. Why browsers wait for CSS
  2. How to see which stylesheets are blocking
  3. The fix, step by step
  4. A deferred loading pattern you can copy
  5. Platform notes
  6. Edge cases and things that go wrong
  7. Keeping the critical path short
  8. Questions and answers

Why browsers wait for CSS

A browser builds a page from two trees: the DOM from your HTML and the CSSOM from your stylesheets. It cannot work out what anything looks like, or where it goes, until the CSSOM is complete for the styles that apply. Painting before then would mean showing raw, unstyled HTML and then redrawing it a moment later, which is the "flash of unstyled content" early browsers were known for. So modern browsers treat every stylesheet linked in the head, whose media condition matches the current screen, as render-blocking.

That rule is sensible, but it means the cost of each blocking stylesheet is added straight onto the time before the visitor sees anything. The cost is not just file size. Each file needs a request, and on a new connection that can mean a DNS lookup, a TCP handshake and a TLS negotiation before the first byte arrives. A stylesheet hosted on a different domain, such as a font service or a CDN you do not otherwise use, pays that connection cost on top.

Stylesheets also delay scripts. A classic script without async or defer that appears after a stylesheet will not run until that stylesheet has loaded, because the script might ask for computed styles. So a slow stylesheet can hold up JavaScript as well as painting.

What does not block

๐Ÿ’ก This guide covers how CSS is delivered. If the problem is that a stylesheet is simply too large because of how it is built, bundled or split, the oversized stylesheets guide deals with that. For scripts that block rendering, see the separate render-blocking JavaScript guide.

How to see which stylesheets are blocking

Start with the CSS Checker, which flags render-blocking stylesheets and measures file size, so you get a list of offenders for each template you test. Then confirm the picture in the browser, because what matters is the order and timing of requests on a real load.

PageSpeed Insights and Lighthouse

Run a mobile test. Recent versions of Lighthouse and PageSpeed Insights report this as a render-blocking requests insight; older versions call it "Eliminate render-blocking resources". Either way it lists each blocking file with its transfer size and an estimate of how long it held up the page. Treat the estimate as a guide to priority, not as an exact saving.

Chrome DevTools

  1. Open DevTools, go to the Network panel, tick Disable cache, filter by CSS and reload. Note every file requested before the first paint and where each one comes from.
  2. Open the Performance panel and record a reload with CPU and network throttling. Look for the first paint marker and see which stylesheet requests finish just before it. Those are the ones on your critical path.
  3. Paste this into the Console after a fresh load to list the files the browser itself marked as blocking:
performance.getEntriesByType('resource')
  .filter(e => e.renderBlockingStatus === 'blocking')
  .map(e => [e.name, Math.round(e.duration) + ' ms', e.transferSize + ' bytes']);

The renderBlockingStatus field is available in Chromium-based browsers. It includes blocking scripts as well as stylesheets, so read the file names.

What a typical problem list looks like

Blocking requestUsual causeFix covered below
Main theme stylesheetWhole site's CSS loaded up frontCritical CSS plus deferred full file
Web font CSS from another domainFont service link in the headSelf-host fonts or preconnect, then defer
A second file that only appears after the first loads@import inside a stylesheetReplace with a link or bundle it
Plugin or widget stylesheetLoaded on every page, used on oneLoad only where needed
Print or large-screen stylesheetNo media attributeAdd the correct media condition

The fix, step by step

Step 1

List every stylesheet that blocks the first paint

Run the CSS Checker and a mobile PageSpeed Insights test on each main template, for example the home page, a product or service page and a blog post. Write down every stylesheet in the head with its origin, transfer size and whether it is yours, the theme's, a plugin's or a third party's. That list tells you which files you can change, which you can only move or remove, and which template benefits most from critical CSS.

Step 2

Remove @import chains and hidden extra requests

Search your stylesheets for @import. The browser only discovers an imported file after it has downloaded and parsed the parent, so each import adds a full round trip before rendering can start. Replace imports with ordinary <link> tags, or better, combine the files at build time. Do the same for web font services: self-host the font files, or at least add a preconnect hint for their domains so the connection starts early.

Step 3

Mark conditional stylesheets with a media attribute

If a stylesheet only applies in some conditions, say so in the link tag. Print styles should carry media="print", and a file used only on wide screens can carry media="(min-width: 64em)". The browser still downloads non-matching files, but at low priority and without delaying the paint. Better still, move small conditional rules into the main file inside @media blocks so there is one fewer request to make.

Step 4

Generate critical CSS for each template

Use a tool such as Critical, Penthouse or Beasties to extract the rules needed to draw the part of each template visible without scrolling. Run it at two viewport sizes, a phone and a laptop, because the first screen differs. Generate per template rather than per URL so the output stays manageable. Check the result by hand: remove rules for elements that are never above the fold, and add any states the tool could not see, such as an open cookie banner.

Step 5

Inline the critical rules in the head

Place the critical rules in an inline style block near the top of the head, before any link to the full stylesheet. Keep the block small, ideally well under about 14 KB after compression, so it arrives in the first few packets of the HTML. Minify it. If your site sends a Content-Security-Policy that restricts inline styles, add a nonce or hash for this block, otherwise the browser will ignore it and the page will render unstyled.

Step 6

Load the full stylesheet without blocking

Change the main link so it does not block, then switch it on once it has arrived. The pattern below sets media="print" on the link, so the browser fetches it without waiting, and a short script switches it to all when it finishes loading. Include a noscript copy of the normal link for visitors without JavaScript. Keep blocking only the stylesheets that genuinely cannot wait, and test that nothing jumps when the full file applies.

Step 7

Test the first paint on a throttled phone profile

Re-run the CSS Checker and PageSpeed Insights, then record a Performance trace in DevTools with slow 4G and CPU throttling. Confirm the first paint now happens before the full stylesheet finishes, that the first screen looks correct at that moment, and that Cumulative Layout Shift has not risen. Check the field data in Search Console's Core Web Vitals report over the following weeks, since lab tests only show one simulated visit.

A deferred loading pattern you can copy

This is a complete head for a template called service on a fictional site, Brightwell Plumbing. The critical rules are inlined, the full stylesheet is fetched without blocking, and the font domain is warmed up early.

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Emergency plumber in Leeds | Brightwell Plumbing</title>

  <!-- 1. Rules for the first screen only, generated at build time -->
  <style>
    :root{--brand:#0b4f6c;--ink:#1d2327}
    body{margin:0;font:1rem/1.5 system-ui,sans-serif;color:var(--ink)}
    .site-header{display:flex;align-items:center;min-height:4rem;padding:0 1rem}
    .hero{padding:2rem 1rem;background:var(--brand);color:#fff}
    .hero h1{font-size:clamp(1.75rem,5vw,2.75rem);margin:0 0 .5rem}
  </style>

  <!-- 2. Full stylesheet: fetched without blocking, applied when loaded -->
  <link rel="stylesheet" href="/css/site.4f2a9c.css" media="print" data-defer>
  <script>
    document.querySelectorAll('link[data-defer]').forEach(function (l) {
      if (l.sheet) { l.media = 'all'; }
      else { l.addEventListener('load', function () { l.media = 'all'; }); }
    });
  </script>
  <noscript><link rel="stylesheet" href="/css/site.4f2a9c.css"></noscript>

  <!-- 3. Print styles never block -->
  <link rel="stylesheet" href="/css/print.css" media="print">
</head>

You will often see a shorter version of this that puts the switch in an inline load handler attribute on the link itself. It works the same way, but a strict Content-Security-Policy blocks inline handler attributes, so the small script block above, which can carry a nonce, is easier to keep working.

An alternative is rel="preload" with as="style", which fetches the file at high priority without applying it, followed by the same switch to a real stylesheet. Preloading makes sense when the full file is needed quickly for content just below the fold. For most small-business sites the print-media pattern is simpler and harder to get wrong.

โš ๏ธ Do not defer the only stylesheet without inlining critical CSS first. The page will paint unstyled and then snap into its real layout, which looks broken and adds layout shift. Deferral and critical CSS belong together.

Platform notes

WordPress

Performance plugins such as WP Rocket, LiteSpeed Cache and Autoptimize can generate critical CSS and load the remaining CSS asynchronously. Switch on one plugin's version of the feature, not two, and clear its cache after theme changes, because stale critical CSS is a common cause of pages that briefly show the wrong layout. Many plugin stylesheets are enqueued on every page; use wp_dequeue_style() in a child theme to remove them from pages that do not use the feature. The WordPress CSS guide covers theme and plugin stylesheets in more depth.

Shopify

Theme stylesheets are output in theme.liquid and in section files. Online Store 2.0 themes already load many component stylesheets only in the sections that need them. App stylesheets injected through content_for_header or app embeds are harder to control; if one blocks rendering on every page, check the app's settings or ask the developer. The Shopify CSS guide has the detail.

Static sites and frameworks

Add critical CSS generation as a build step, so it is rebuilt every time styles change. Next.js, Nuxt and Astro can inline or split CSS per route, and some offer an inlining option or plugin. Check the built HTML rather than assuming: open the page source and confirm the head contains the inline block and only the links you expect.

Edge cases and things that go wrong

Keeping the critical path short

Render-blocking CSS tends to creep back as plugins, apps and marketing tags are added. A few habits keep it under control:

  1. Keep a short record of which stylesheets each template is allowed to block on, and check new additions against it.
  2. Regenerate critical CSS automatically in your build or deployment, never by hand.
  3. Ban @import in production stylesheets with a linter rule, so it cannot sneak back.
  4. Re-run the CSS Checker after installing any plugin, app or widget, and after theme updates.
  5. Watch the Core Web Vitals report in Search Console for FCP and LCP changes that line up with deployments.

For how this work fits into the wider picture of loading speed, see the LCP guide and the Core Web Vitals guide.

Questions and answers

1. Is all CSS render-blocking?

No. Only stylesheets that the browser needs before it can paint are render-blocking: those linked in the head whose media condition matches the current screen. A stylesheet marked with a media attribute that does not match, such as print, is still downloaded but does not hold up the first paint. Stylesheets added later by script do not block the first render either. Inline style blocks do not need a network request, although the browser still has to parse them before painting.

2. How big should critical CSS be?

As small as you can make it while the first screen still looks right. A common target is to keep the inline block well under about 14 KB after compression, because that amount can usually arrive with the first packets of the HTML response. Much larger and you are sending the same bytes again with every page view, since inline CSS is not cached separately. If your critical CSS is very large, the design of the first screen or the tool settings probably need a closer look.

3. Will deferring CSS cause a flash of unstyled content?

It will if you defer the stylesheet without inlining critical CSS first. The browser paints as soon as it can, and without any rules for the first screen it paints raw HTML. With good critical CSS in place, the first screen looks correct straight away and the full stylesheet only styles content further down or interactive states. Test on a throttled connection, where any gap between the first paint and the full stylesheet arriving is easy to see.

4. Does preload fix render-blocking CSS on its own?

Not by itself. Preload tells the browser to fetch a file early and at high priority, but it does not change whether a normal stylesheet link blocks rendering. If you add a preload and keep the ordinary blocking link, the file simply starts downloading slightly earlier. Preload helps when it replaces the blocking link as part of a pattern that applies the stylesheet once it has loaded, or when a file is discovered late, such as one referenced from another stylesheet.

5. Should I inline all my CSS instead?

Only for very small sites where the whole stylesheet is tiny. Inlining everything removes the request, but the CSS is then sent again with every page the visitor opens, and the browser cannot cache it. For most sites the better balance is to inline the rules for the first screen and keep everything else in an external file with a long cache lifetime and a versioned file name, so repeat visits and later pages load it from cache.

6. Why is a Google Fonts stylesheet flagged as render-blocking?

Because it is a stylesheet in the head from another domain. The browser has to connect to that domain, download the CSS, and only then can it paint. You can reduce the cost by adding preconnect hints for the font domains, but the most reliable fix is to self-host the font files and put the font-face rules in your own CSS or critical block. Remember that the font files themselves still download separately after the CSS.

7. Does fixing render-blocking CSS improve rankings?

It can help indirectly. Google uses Core Web Vitals as one of many page experience signals, and render-blocking CSS mainly affects First Contentful Paint and Largest Contentful Paint. A faster first paint also means fewer visitors give up before the page appears. But relevance and content quality matter far more, so treat this as part of making the site fast for people, not as a ranking trick. Measure field data before and after to see real effects.

Find the stylesheets holding up your pages

The CSS Checker flags render-blocking stylesheets and measures stylesheet size, alongside validation errors, unused rules, specificity issues and prefix gaps, so you can see which CSS to deal with first.

Open CSS Checker Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All CSS Checker Fixes  ·  Fixing Unused CSS  ·  Fixing Oversized Stylesheets  ·  Render-Blocking JavaScript  ·  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.