Skip to content

Injecting Critical CSS

Generating and Injecting Critical CSS

Critical CSS is the minimal set of styles required to render the above-the-fold content of a webpage. By extracting and injecting this CSS early, you reduce render-blocking delays and improve Largest Contentful Paint (LCP) and First Contentful Paint (FCP). This section explains how to generate and inject critical CSS using tools like PurgeCSS and the purgecss-plugin-critical plugin.


1. Identify the Critical Rendering Path

Before generating critical CSS, identify the elements that make up the above-the-fold content. Use tools like Lighthouse or Chrome DevTools to analyze the critical rendering path. For dynamic content, manually inspect the DOM to ensure all visible elements are included.

Example:
If your homepage has a hero section with a heading, image, and button, these elements define the critical rendering path.


2. Generate Critical CSS with PurgeCSS

PurgeCSS is a tool that removes unused CSS from your project. The purgecss-plugin-critical plugin extends this to extract critical CSS by analyzing the DOM.

Step-by-Step Setup

  1. Install dependencies:

    npm install purgecss purgecss-plugin-critical
    

  2. Configure PurgeCSS: Create a purgecss.config.js file to define your project's CSS files and purge rules:

    module.exports = {
      content: ['./src/**/*.html', './src/**/*.js', './src/**/*.jsx'],
      css: ['./src/styles/global.css'],
      plugins: [
        require('purgecss-plugin-critical')({
          // Optional: specify critical elements (e.g., IDs or classes)
          criticalElements: ['#hero', '.logo', '.cta-button'],
        }),
      ],
    };
    

  3. Run PurgeCSS:

    npx purgecss --config purgecss.config.js
    
    This generates a critical.css file containing only the styles needed for the specified elements.


3. Inject Critical CSS into HTML

Inject the generated critical.css into the <head> of your HTML to ensure it loads before other CSS. Use a script to dynamically add the <style> tag.

Example: Dynamic Injection

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>My Site</title>
  <style id="critical-styles"></style>
</head>
<body>
  <!-- Your page content -->
  <script>
    const criticalCSS = document.createTextNode(`
      /* Paste your critical.css content here */
      #hero { color: #fff; }
      .logo { font-size: 24px; }
      .cta-button { background: #007bff; }
    `);
    document.getElementById('critical-styles').appendChild(criticalCSS);
  </script>
</body>
</html>

Alternative: Build-Time Injection

In frameworks like Next.js, use next.config.js to inject critical CSS during the build process:

module.exports = {
  webpack(config, { isServer }) {
    if (!isServer) {
      config.entry('main').prepend('./src/critical.css');
    }
    return config;
  },
};


4. Load Non-Critical CSS Asynchronously

After injecting critical CSS, load the rest of your styles asynchronously to avoid blocking rendering. Use <link rel="preload"> or @media queries to defer non-critical styles.

Example:

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


5. Validate with Lighthouse

Use Lighthouse to audit your page and ensure critical CSS is optimized: 1. Open Chrome DevTools → Audits → Run audit. 2. Check the Performance score and verify that critical CSS is below 15KB (recommended).


Key takeaways

  • Generate critical CSS using PurgeCSS with the purgecss-plugin-critical plugin to isolate styles for above-the-fold content.
  • Inject critical CSS into the <head> dynamically or during the build process to ensure it loads first.
  • Load non-critical CSS asynchronously to avoid render-blocking and improve LCP/FCP.
  • Validate results with Lighthouse to ensure critical CSS is minimal and effective.