Why CSS blocks rendering

CSS files are render-blocking resources: the browser must download and process them before it can paint anything on screen. Pages with unnecessarily large style sheets therefore take longer to reach First Contentful Paint (FCP). By deferring non-critical CSS, you can shorten the Critical Rendering Path.

Consider a page with an accordion containing hidden paragraphs, each styled by a different class. The page's stylesheet defines eight classes, but only some are needed to render the visible content—the title, subtitle, and accordion buttons. The rest only affect content that isn't immediately visible.

Measuring the impact

To see the problem in action, open the demo in Chrome and use DevTools:

  1. Open Chrome DevTools.
  2. Select the Performance panel and reload the page.
Lighthouse
    report for unoptimized page, showing FCP of '1s' and 'Eliminate blocking
    resources' under 'Opportunities'
The Lighthouse report suggests simplifying your style sheet to make your page load faster.

The report shows an FCP of "1s" and flags Eliminate render-blocking resources, pointing at style.css. In the trace, the FCP marker appears only after the CSS finishes loading—the browser waits for all styles before painting a single pixel.

DevTools performance trace for unoptimized page, showing FCP starting after CSS loads.
On the unoptimized demo page, FCP can't happen until the CSS finishes loading.

Separating critical from non-critical styles

Use DevTools' Coverage Tool to identify which classes are actually required for initial render:

  1. Open the Command Menu with Control+Shift+P or Command+Shift+P (Mac).
  2. Type "Coverage" and select Show Coverage.
  3. Click Reload to start capturing coverage.
Coverage for CSS file, showing 55.9% unused bytes.
The coverage report shows how much of your CSS is actually used in the initial page load.

In the report, classes marked in green are critical—they style visible content. Classes marked in red are non-critical, affecting only content that is not immediately visible, such as the hidden paragraphs.

Inlining critical CSS

Extract the green classes and place them inside a <style> block in the document head:

<style type="text/css">
.accordion-btn {background-color: #ADD8E6;color: #444;cursor: pointer;padding: 18px;width: 100%;border: none;text-align: left;outline: none;font-size: 15px;transition: 0.4s;}.container {padding: 0 18px;display: none;background-color: white;overflow: hidden;}h1 {word-spacing: 5px;color: blue;font-weight: bold;text-align: center;}
</style>

Loading the rest asynchronously

Load the remaining classes with a non-blocking pattern:

<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

This differs from standard CSS loading. Here's what each piece does:

  • link rel="preload" as="style" fetches the stylesheet asynchronously.
  • The onload attribute tells the browser to process the CSS once the download completes.
  • Setting onload to null after it runs prevents some browsers from re-invoking the handler when they switch the rel attribute.
  • The noscript reference provides a fallback for browsers without JavaScript.

Production considerations

For production, prefer a purpose-built helper like loadCSS, which encapsulates this behavior and handles cross-browser edge cases. These functions also support Content Security Policy, which may disallow inline onload JavaScript.

An alternative is placing the CSS link at the bottom of the page so content can render before the stylesheet arrives. However, browsers still prioritize the stylesheet, so it can continue to block critical content.

Verifying the result

Run another Performance trace on the optimized page. The FCP marker now appears before the browser even requests the CSS, since it no longer waits for those styles to render:

DevTools
    performance trace for optimized page, showing FCP starting before CSS
    loads.
On the optimized page, FCP can start before the style sheet loads.

A final Lighthouse run shows FCP reduced by 0.2s—a 20% improvement—and Eliminate render-blocking resources now appears under Passed Audits rather than Opportunities:

Lighthouse report, showing an FCP value of '0.8s'.
A depiction
    of Lighthouse report, showing 'Eliminate blocking resources' on the 'Passed
    Audits' section.
The page now passes the blocking resources audit.

For more complex setups, the extract critical CSS guide covers popular tooling for automating this process, with a codelab to see those tools in practice.