ShrinkRay All Articles
Developer Productivity

Your Stylesheet Called — It Wants Its 180KB Back

By ShrinkRay Developer Productivity
Your Stylesheet Called — It Wants Its 180KB Back

There's a running joke in frontend circles that JavaScript gets all the blame while CSS sits quietly in the corner, looking innocent. The thing is, CSS isn't innocent. It's just better at hiding the evidence.

Open Chrome DevTools on almost any production site built with a popular UI framework and flip over to the Coverage tab. What you'll find is genuinely alarming: stylesheets pushing 200KB, 300KB, sometimes more — with usage rates hovering somewhere between embarrassing and catastrophic. We're talking 10%, 15% actually rendered on screen. The rest? Dead weight, riding along in every single page load, taxing parse time, blocking render, and quietly torching your Core Web Vitals.

So why does this keep happening?

The Framework Trap Nobody Warns You About

It usually starts innocently enough. You spin up a new project, drop in Bootstrap, Tailwind, or Material UI, and suddenly you've got a world-class design system at your fingertips. The problem is you also just imported the entire world-class design system — accordion components you'll never use, grid utilities for layouts you haven't built, color palettes for a brand refresh that hasn't happened yet.

Bootstrap's full CSS clocks in around 190KB unminified. Tailwind's default build, before any configuration, generates somewhere north of 3MB in older versions — yes, megabytes. Even with modern JIT compilation, a misconfigured Tailwind setup can still ship thousands of unused utility classes if your content paths aren't dialed in.

Most teams configure the framework once during setup and never revisit it. The project ships, the stylesheet stays fat, and everyone moves on.

Refactor Debt Accumulates in Silence

Frameworks aren't the only culprit. Your own code is doing damage too.

Every time a component gets redesigned, a page gets retired, or a feature gets yanked from the roadmap, there's a decent chance the CSS that powered it is still sitting in your stylesheet. Unlike JavaScript, where a dead function at least has the decency to be obviously unused, CSS doesn't throw errors when its selectors match nothing. It just keeps showing up. Silently. Faithfully. Uselessly.

In a codebase that's been around for two or three years, this accumulates fast. One team at a mid-sized SaaS company did an audit after three years of growth and found over 40% of their stylesheet was referencing component classes that no longer existed anywhere in their HTML. That's not an edge case — that's a normal outcome for any project that doesn't actively fight CSS rot.

Utility Classes Gone Sideways

Tailwind and similar utility-first frameworks promised to solve the dead CSS problem by generating only what you use. And they largely deliver on that promise — when configured correctly. When they're not, they can actually make things worse.

Common failure modes include:

The result is a utility-first project that ends up with more CSS than the component-based approach it was supposed to replace.

Auditing What You Actually Use

Before you start deleting things, you need a clear picture of what's actually being used. A few tools make this genuinely painless:

Chrome DevTools Coverage Panel is the fastest starting point. Hit Cmd+Shift+P, type "Coverage," start recording, and navigate around your app. It highlights unused CSS in red, line by line. It won't catch dynamic states or edge-case interactions, but it gives you a solid baseline.

PurgeCSS is the workhorse for automated removal. It scans your HTML, JavaScript, and template files, identifies selectors that appear in your content, and strips everything else. It integrates cleanly with PostCSS, webpack, Vite, and most modern build pipelines. The key is being thorough with your content configuration — if PurgeCSS doesn't see a file, it'll purge the classes it references.

UnCSS takes a slightly different approach, actually rendering your pages in a headless browser and checking which rules apply. It's slower but more accurate for dynamic applications where class names get added at runtime.

Stylelint with the no-unused-selector plugin can catch some dead code at the linting stage, though it's more effective in tightly coupled component architectures than sprawling utility setups.

The Pruning Playbook

Once you know what's bloated, here's how to actually fix it without torching your design system:

Step 1: Scope your framework imports. If you're using Bootstrap, stop importing the whole thing. Import only the modules you need — grid, buttons, forms — and skip the rest. Most major frameworks support this kind of à la carte approach.

Step 2: Configure your utility framework's content paths precisely. In Tailwind, this means listing every file type that might contain class names — .js, .jsx, .ts, .tsx, .html, .vue — and making sure you're not accidentally including node_modules or build artifacts.

Step 3: Automate PurgeCSS in your build pipeline. Don't make this a manual step. Wire it into your production build so it runs every time. Set it up once, test thoroughly, and let it work.

Step 4: Add a bundle size budget. Tools like bundlesize or built-in Vite/webpack performance hints can fail your build if CSS crosses a threshold you define. This turns size regression from a silent problem into a visible one.

Step 5: Do a quarterly dead-code pass. Set a calendar reminder. Run Coverage, look for patterns, and delete selectors that haven't matched anything in months. It's not glamorous, but neither is shipping 200KB of CSS to mobile users on a 4G connection.

What You Stand to Gain

The payoff here isn't abstract. Smaller stylesheets mean faster parse times — CSS is render-blocking by default, so every unnecessary kilobyte is directly delaying your first paint. Teams that have done serious CSS audits routinely report 60–80% reductions in stylesheet size. Going from 220KB to 40KB isn't unusual once you combine framework pruning with automated removal.

For a site doing a million pageviews a month, that delta translates into real bandwidth savings, real improvements in Largest Contentful Paint, and real score bumps in Lighthouse — which, depending on your business, can mean real money in organic search.

JavaScript deserves the scrutiny it gets. But if you've spent weeks optimizing your JS bundles while your stylesheet quietly sits at 250KB with 18% utilization, you're leaving the biggest gains on the table.

Shrink the stylesheet. Ship the rest.