Feedback

Reduce Unused CSS

By Christian Schreiber ยท Updated

When PageSpeed Insights or Lighthouse tells you to reduce unused CSS, it has found stylesheet rules that your page downloads and parses but never applies to any element. Usually the cause is one global stylesheet that makes every page carry the styles of every other page. Because stylesheets block rendering, those unused rules delay the moment the visitor sees anything at all.

From PerfDelta's measurements: Lighthouse reports this finding on 67% of 4,108 measured home pages. The median estimated saving is 450 ms. More in the data section below.

What the unused-css-rules audit measures

Lighthouse runs the same coverage analysis it uses for unused JavaScript against your stylesheets. It loads the page, records which CSS rules matched an element during that load, and treats the rest as unused. For each stylesheet it reports the transfer size and the estimated savings, meaning the bytes you could avoid sending if the unused rules were gone.

The result is a snapshot of one load in one viewport. Rules for a modal that opens on click, a :hover state or a wider breakpoint count as unused even though the site needs them. Treat the number as a pointer to oversized stylesheets, not a delete list.

Unused CSS delays FCP and LCP through render blocking

A <link rel="stylesheet"> in the head is render-blocking by default. The browser must download and parse the whole file and build the CSSOM before it paints, so unused CSS is extra bytes directly on the critical path. A smaller stylesheet arrives and parses sooner, which moves First Contentful Paint and Largest Contentful Paint forward. The fix overlaps closely with eliminating render-blocking resources, because trimming the stylesheet is the most direct way to shorten that blocking time.

Find unused CSS with the Coverage panel

Open Chrome DevTools, press Ctrl+Shift+P (Cmd+Shift+P on a Mac), run Show Coverage and reload the page. The Coverage tab lists every CSS and JavaScript file with a bar split into used and unused bytes. Click a file to see its unused rules marked line by line.

Two habits make the data more useful:

Remove unused CSS at build time

The most reliable fix removes unused selectors before the file ever ships. PurgeCSS scans your templates and scripts for class names, IDs and element selectors and strips any rule whose selector never appears:

// purgecss.config.js
module.exports = {
  content: ['./templates/**/*.php', './src/**/*.{html,js,jsx}'],
  css: ['./src/styles.css'],
  safelist: ['is-active', 'is-open', /^modal-/],
};

Run it with npx purgecss --config ./purgecss.config.js --output ./dist/css/ or through its PostCSS plugin in your existing build. The content list must cover every file that can output a class name, otherwise purged pages lose styles.

Tailwind CSS generates only the classes it finds

Tailwind scans your source files and generates only the utilities it finds, so an accurate source configuration is the most important setting for output size. In Tailwind v3 that is the content array:

// tailwind.config.js
module.exports = {
  content: ['./src/**/*.{html,js,jsx,php}'],
};

Tailwind v4 detects sources automatically and lets you add paths it would miss with the @source directive in your CSS. In both versions, write complete class names: a class assembled from fragments, such as 'bg-' + color + '-500', is invisible to the scanner.

Inline critical CSS and load the rest asynchronously

Inline the small amount of CSS required for above-the-fold content in the <head>, then load the full stylesheet without blocking:

<style>/* critical above-the-fold rules */</style>
<link rel="preload" href="/styles.css" as="style"
      onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>

Tools such as the critical npm package extract these rules from a rendered page. If the inline block misses a rule the first screen needs, visitors see a brief flash of unstyled content. Stylesheets that only apply to certain conditions can also carry a media attribute, for example media="print", and the browser does not block rendering on a stylesheet whose media query does not match.

Split CSS per route and component

A single stylesheet for the whole site forces every page to download styles it does not use. Splitting CSS by template or component keeps each file close to what the page needs. On a server-rendered site, one base stylesheet plus a small file per template is often enough.

In React and Next.js, CSS Modules scope styles to the component that imports them, and the bundler emits the CSS with the code that uses it. In the Next.js App Router, CSS imported in a route segment loads with that segment, while global CSS in the root layout loads everywhere, so keep that file small.

Framework and theme bloat: Bootstrap and page builders

The full compiled Bootstrap stylesheet ships many components you never render. Its Sass source lets you import only what you use, after the required files; check the documentation for the exact order in your version:

// custom-bootstrap.scss
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/root";

@import "bootstrap/scss/reboot";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/buttons";

Page builders and multipurpose themes ship CSS for every widget they offer. Disable unused modules in the builder's settings where possible, and prefer a lighter theme for new projects.

Reduce unused CSS in WordPress

In WordPress, most unused CSS comes from plugins that enqueue stylesheets on every page, although their form or slider appears on only one. Work in this order:

  1. Remove plugins you no longer need. Each active plugin can add sitewide CSS.
  2. Unload stylesheets where they are not used. Asset managers such as Perfmatters or Asset CleanUp let you disable a stylesheet per page or post type without code. In a child theme you can do the same with wp_dequeue_style() and a conditional tag:
add_action('wp_enqueue_scripts', function () {
    if (!is_page('contact')) {
        wp_dequeue_style('contact-form-7');
    }
}, 100);
  1. Use "remove unused CSS" features with care. WP Rocket, LiteSpeed Cache and Perfmatters can generate a reduced stylesheet per page and load the full one later or not at all. This often shrinks the audit result sharply, but the reduced CSS is built from a rendered snapshot, so styles for menus, popups and cookie banners added by JavaScript can go missing. The files must be regenerated after theme changes, and some implementations rely on an external service. Test every key template and interactive element after enabling it.

Reduce unused CSS in Shopify themes

Shopify themes typically load a base stylesheet on every page from theme.liquid. Newer themes such as Dawn move component styles into section files, so the CSS only loads where the section is used:

{{ 'section-product-reviews.css' | asset_url | stylesheet_tag }}

Follow that pattern for your own customisations instead of adding everything to the base file. Apps are the other source: older apps that inserted code into the theme can keep loading stylesheets after removal, so check theme.liquid and your snippets for leftover references.

Common mistakes: purged JavaScript classes and missing safelists

How to verify the fix

Rebuild, re-run Lighthouse or PageSpeed Insights and confirm that the unused-css-rules audit reports fewer wasted bytes and FCP has improved. Click through menus and popups on each key template to confirm no styles were lost. PerfDelta tests several pages of your site on mobile and desktop and lists the Lighthouse opportunities with estimated savings and the affected files, so template differences are easy to spot. Lab results change immediately, while field data in the Chrome UX Report reflects a trailing 28-day window.

Frequently asked questions

What does "reduce unused CSS" mean?

It means your page loads stylesheet rules that match no element during the page load. The browser still downloads and parses them before it paints, so they delay rendering without contributing anything to the page.

How do I find unused CSS on my page?

Use the Coverage panel in Chrome DevTools. Run Show Coverage from the command menu, reload the page and interact with it. The unused share of each stylesheet is shown per file, and clicking a file marks the unused rules line by line.

Can removing unused CSS break my site?

Yes, if a tool removes classes that JavaScript, a CMS editor or a widget adds at runtime, because they do not appear in the scanned files. Safelist those classes and test every key template after each build.

How do I remove unused CSS with Tailwind?

Tailwind only generates the classes it finds in your source files. Make sure every file that uses classes is included in the content configuration or detected sources, and write complete class names instead of building them from string fragments.

Should I use the remove unused CSS feature in my WordPress caching plugin?

It can shrink the result sharply, but the reduced CSS is built from a snapshot of the page and can miss styles for menus, popups and other elements added by JavaScript. Enable it, test interactive elements on every key template and regenerate the CSS after theme changes.

What PerfDelta's measurements show

Lighthouse reports this finding on 67% of 4,108 measured home pages. The median estimated saving is 450 ms.

Data as of October 16, 2026, recalculated daily. Source: PerfDelta's own measurements (Chrome UX Report and Lighthouse); details in the website speed statistics and the methodology.

Thresholds and sources

Sources:

All sources retrieved on October 9, 2026. Thresholds and documentation change; the linked page is authoritative.

Test your site

Run a free scan to see whether this applies to your pages, on mobile and desktop, with lab and field data side by side.

Run a free test

A free account saves your tests and shows how your values change from one test to the next. Daily monitoring with field data and alerts starts with the Solo plan.

Related audits