Dead CSS Removal Workflow

Created: 2025-11-28
Tools: Lighthouse MCP, CSS MCP, Browser Tools, grep

Overview

Removing unused CSS improves page load performance, reduces bundle size, and makes stylesheets easier to maintain. However, there is no magic button that safely removes CSS automatically—static analysis tools can't detect dynamically-generated class names (Stimulus, Rails helpers, JavaScript).

This document outlines a safe, methodical workflow using AI-assisted tools available in Cursor.

Why Not Just Use PurgeCSS?

Tools like PurgeCSS work well for static sites but are risky for Rails applications because:

  • Dynamic classes: class: "btn-#{variant}" in Ruby
  • Stimulus controllers: Classes added via JavaScript
  • Conditional rendering: Classes only used in specific states
  • Third-party components: Bootstrap, Font Awesome classes

The workflow below uses targeted analysis instead of aggressive purging.


Phase 1: Identify Unused CSS

Step 1.1: Run Lighthouse Audit

First, identify which CSS files have the most unused code:

Run a Lighthouse performance audit on https://www.warmlyyours.me:3000
Focus on the "Reduce unused CSS" opportunity

Expected output: File paths, estimated savings, and coverage percentages.

Step 1.2: Get Detailed Coverage Report

For deeper analysis, use Chrome DevTools Coverage:

Navigate to https://www.warmlyyours.me:3000
Take a screenshot showing the page loaded

Then manually:

  1. Open DevTools → Coverage tab (Cmd+Shift+P → "Coverage")
  2. Click reload to capture CSS usage
  3. Look for files with high "Unused Bytes" percentage

Step 1.3: Analyze Specific Stylesheets

Once you identify problem files, analyze their complexity:

Analyze the CSS in client/stylesheets/www/03-components/page-blog.scss
for unused patterns and complexity issues

Phase 2: Verify Before Deleting

Step 2.1: Search for Class Usage

Never delete a class without searching the entire codebase first.

Search for the class "hero-wrapper-old" in app/views, app/components, 
and client/js directories. Is it used anywhere?

Or use grep directly:

# Search for a specific class
grep -r "hero-wrapper-old" app/ client/ --include="*.erb" --include="*.rb" --include="*.js" --include="*.scss"

# Search for partial class names (dynamic classes)
grep -r "hero-wrapper" app/ client/ --include="*.erb" --include="*.rb"

Step 2.2: Check for Dynamic Class Generation

Look for patterns that generate classes dynamically:

# Rails helpers
class: "card-#{type}"
class_names("active" => condition)

# Stimulus
element.classList.add("loading")
this.element.classList.toggle("open")

Ask the AI:

Are there any dynamic class patterns in app/helpers or app/javascript 
that might generate classes starting with "hero-"?

Step 2.3: Check Bootstrap/Framework Classes

Before removing a class, verify it's not from Bootstrap:

Is "d-flex" a Bootstrap utility class? What does it do?
Check browser compatibility for the CSS property "gap" in flexbox

Phase 3: Safe Removal

Step 3.1: Remove One Class at a Time

Don't batch-delete. Remove classes individually and verify:

Delete the .hero-wrapper-old class from client/stylesheets/www/03-components/hero.scss

Step 3.2: Rebuild Assets

After each change:

eval "$(mise activate zsh)" && yarn build

Step 3.3: Visual Regression Check

Take before/after screenshots to catch layout shifts:

Take a screenshot of https://www.warmlyyours.me:3000 

Compare with the previous state. Look for:

  • Missing elements
  • Broken layouts
  • Shifted content
  • Missing hover states

Step 3.4: Test Critical Pages

After removing CSS, audit affected pages:

Run Lighthouse on the homepage, a product page, and the contact form
to verify no accessibility or performance regression

Phase 4: Ongoing Maintenance

4.1: Prevent Dead CSS Accumulation

  1. Use component-scoped CSS: Keep styles close to their components
  2. Document class purpose: Add comments for non-obvious classes
  3. Review during PRs: Check if new CSS duplicates existing styles
  4. Regular audits: Run Lighthouse monthly

4.2: Safe Patterns for Dynamic Classes

When you need dynamic classes, use allowlists:

// _safelist.scss - Classes that might appear unused but are dynamically generated
// Do not remove these without checking JavaScript/Ruby code

// Used by Stimulus controllers
.is-loading { }
.is-active { }
.is-open { }

// Used by Rails helpers
.alert-success { }
.alert-danger { }
.alert-warning { }

4.3: Document Removed CSS

Keep a log of what was removed and why:

## CSS Cleanup Log

### 2025-11-28
- Removed `.hero-wrapper-old` - replaced by `.hero-container` in refactor
- Removed `.legacy-button` - unused since Bootstrap 5 migration
- Kept `.card-highlight` - used dynamically in product_card_helper.rb

Quick Reference: MCP Commands

Task Prompt
Audit performance Run Lighthouse audit on [URL]
Check CSS property What are the values for CSS [property]?
Browser support Is CSS [feature] supported in Safari?
Analyze CSS file Analyze the CSS in [file] for issues
Search codebase Search for class "[name]" in app/views
Take screenshot Take a screenshot of [URL]

Example Workflow Session

Here's a complete example of removing dead CSS:

1. Identify Problem

Run Lighthouse performance audit on https://www.warmlyyours.me:3000/floor-heating
What's the "Reduce unused CSS" recommendation?

AI Response: "The page has 45KB of unused CSS, primarily from webpack-bundle.css. Top unused selectors include .legacy-carousel, .old-modal, .deprecated-grid..."

2. Verify Usage

Search for "legacy-carousel" in app/views, app/components, and client/js.
Is this class used anywhere?

AI Response: "No matches found in app/views or app/components. Found 1 match in client/stylesheets/www/03-components/carousel.scss (the definition itself)."

3. Check for Dynamic Usage

Search for "legacy" or "carousel" patterns in app/helpers that might 
generate this class dynamically

AI Response: "No dynamic patterns found that would generate legacy-carousel."

4. Remove Safely

Delete the .legacy-carousel class and its related styles from 
client/stylesheets/www/03-components/carousel.scss

5. Rebuild and Verify

eval "$(mise activate zsh)" && yarn build
Take a screenshot of https://www.warmlyyours.me:3000/floor-heating

6. Final Audit

Run Lighthouse on the same page. Did the unused CSS decrease?

Troubleshooting

"I deleted a class and something broke"

  1. git checkout -- [file] to restore the file
  2. Search more broadly: grep -r "partial-class-name" .
  3. Check JavaScript files for classList.add() calls
  4. Look for Ruby string interpolation: "class-#{variable}"

"Lighthouse shows unused CSS but I can't find it"

  • The CSS might be from a vendor library (Bootstrap, Font Awesome)
  • The CSS might only be used on other pages
  • The CSS might be loaded but apply to elements not on the current page

"The class is used but Lighthouse still flags it"

This is normal—Lighthouse only analyzes the current page state. A class used on hover, after JavaScript runs, or on different screen sizes may be flagged as "unused" but is actually needed.


Related Documentation