# Render-blocking CSS eliminated or inlined

- **Pattern:** `ab-001998` (`performance-core.loading-resource-priority.render-blocking-css`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001998
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001998)

## Why it matters

A render-blocking stylesheet halts all HTML parsing and painting until the browser has fully downloaded and parsed the CSS file (ISO-25010 time-behaviour). On a 3G connection, a 145 KB uncompressed stylesheet can block rendering for 800–1200ms on its own. Tailwind's JIT output, bundled third-party component libraries, and global reset files are common offenders — they pull in styles for elements that are not in the initial viewport, making the user wait for CSS they do not need until the page scrolls.

## Severity rationale

High because render-blocking CSS directly delays First Contentful Paint and LCP, and the penalty scales with file size and network conditions.

## Remediation

Split CSS into critical (above-fold) and non-critical (below-fold). Inline critical styles and load the rest asynchronously in your root `<head>`:

```html
<!-- Inline critical CSS — keep under 14 KB -->
<style>{criticalCSS}</style>

<!-- Defer non-critical stylesheet -->
<link rel="preload" as="style" href="/styles/non-critical.css"
      onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles/non-critical.css"></noscript>
```

For print or conditional styles, use `media` attributes to prevent render blocking:
```html
<link rel="stylesheet" href="/styles/print.css" media="print">
```

For Tailwind projects, verify your `content` array in `tailwind.config.ts` is not too broad — unused class purging is essential to keeping the output small.

## Detection

- **ID:** `render-blocking-css`
- **Severity:** `high`
- **What to look for:** Count all relevant instances and enumerate each. Check HTML source for `<link rel="stylesheet">` tags without `media` attributes or with `media="all"` or `media="screen"`. These block rendering. Also check for embedded `<style>` tags and their sizes. Look for critical CSS inlining patterns or `<link rel="preload">` with `onload` handlers for deferred styles.
- **Pass criteria:** Non-critical CSS is deferred via `media` queries or async loading patterns. Critical CSS (under 14KB) is inlined for above-fold content. `<link rel="preload" as="style" href="...">` used for async CSS loading.
- **Fail criteria:** All CSS is render-blocking (large monolithic stylesheet loaded synchronously), or no distinction between critical and non-critical CSS. Initial stylesheets exceed 20KB.
- **Skip (N/A) when:** The project has no CSS or uses CSS-in-JS that doesn't produce external stylesheets.
- **Detail on fail:** Specify the blocking stylesheet size. Example: `"main.css 145KB loaded render-blocking in <head>; media attribute not used. Critical CSS not identified or inlined"` or `"Tailwind CSS output 78KB not split; no critical/non-critical separation"`.
- **Remediation:** Non-critical CSS should not block rendering. Separate your CSS into critical (above-fold) and non-critical (below-fold):

  ```html
  <!-- Critical CSS inlined -->
  <style>{criticalCSS}</style>

  <!-- Non-critical CSS deferred -->
  <link rel="preload" as="style" href="non-critical.css" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="non-critical.css"></noscript>
  ```

  Or use `media` attributes for print or non-essential styles:
  ```html
  <link rel="stylesheet" href="print.css" media="print">
  ```

## External references

- iso-25010 performance-efficiency.time-behaviour

Taxons: performance

HTML version: https://auditbuffet.com/patterns/ab-001998
