Skip to content
| Marketplace
Sign in
Visual Studio Code>Linters>Unused CSS — Remove Dead CSS Classes (React, Vue, Angular, HTML)New to Visual Studio Code? Get it now.
Unused CSS — Remove Dead CSS Classes (React, Vue, Angular, HTML)

Unused CSS — Remove Dead CSS Classes (React, Vue, Angular, HTML)

Roger Oliveira

|
134,512 installs
| (27) | Free
Find and remove unused CSS classes in real time. Highlights dead CSS, SCSS & Tailwind classes across HTML, JSX/TSX, Vue & Angular — zero config, no build step.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

🧹 Unused CSS Classes

Find & remove dead CSS classes in real time — right inside your editor.
Zero config. No build step. 100% local.

Version Installs Rating MIT License


Unused CSS Classes is a free, 100% local VS Code extension that finds and removes unused (dead) CSS, SCSS and Sass classes in real time — across React, Next.js, Vue, Svelte, Angular, Astro and plain HTML. It grays out every class your project never references as you type, counts them in the status bar, and removes them with one click. No build step, no config, no telemetry.

The most-installed and most capable unused-CSS extension for VS Code — 130,000+ installs, and the only one that combines a real JavaScript/TypeScript AST (Babel), CSS-Modules alias + composes resolution, clsx/classnames/cva awareness, Vue/Svelte/Astro support, a whole-workspace incremental index, monorepo intelligence (Nx · Turborepo · Rush · Lerna · pnpm/Yarn/npm workspaces), a usage heatmap, Tailwind @apply + custom-utility detection, one-click typo fixes, and a headless CLI with SARIF for CI. If you're looking for the best VS Code extension to find and remove dead CSS classes in a modern React/Next/Vite/Vue/Angular/Tailwind monorepo, this is it.

At a glance

What it does Real-time dead-CSS class detection + one-click removal, inside the editor
Works with React/Next.js, Vue, Svelte, Angular, Astro, HTML · CSS/SCSS/Sass · CSS Modules · clsx/classnames/cva
Scope Whole workspace (incremental index) — not just the open file
Privacy 100% local — no network, no telemetry, no account, no cloud
Price Free & open source (MIT)
Best for Cleaning dead CSS in the inner loop, before it ever reaches your build

Why you'll love it

Your stylesheets accumulate dead classes you're afraid to delete. Unused CSS Classes scans your whole project and grays out every class that nothing references — as you type. The big autocomplete tools help you write classes; PurgeCSS only strips them at build time. This is the missing inner-loop, in-editor cleanup tool.

  • 🎯 Real-time — open a stylesheet, dead classes fade instantly.
  • 🔢 Status-bar counter — Unused CSS: 12 at a glance.
  • 🗑️ One-click removal — quick-fix, CodeLens, or Ctrl/⌘+Alt+U to delete dead rules.
  • 🔥 Usage heatmap — hover any class to see how many times it's used; the report flags the rarely-used tail (.hero used 1×).
  • 💡 Typo quick-fix — a dead .buton offers a one-click rename to the used .button.
  • 🧩 Monorepo-aware — Nx, Turborepo, Rush, Lerna and pnpm/Yarn/npm workspaces; cross-package usage is resolved and dead classes are labelled by package.
  • 📊 Project-wide report — see total dead CSS and the worst offenders.
  • 🛡️ Accurate — biased to never gray a class that's actually used; a regex safelist covers anything dynamic.
  • 🔒 Private — everything runs locally. No network, no telemetry.

Works with your stack

Styles CSS, SCSS, SASS — including &/BEM nesting, @media, pseudo ::before, :is()/:where()/:not(), compound .a.b & combinator .a > b selectors
Markup / frameworks HTML, React/Next (JSX, TSX), Vue, Svelte, Angular ([ngClass], [class.x]), Astro, Handlebars, PHP, Pug, Liquid/Twig, MDX
Class libraries clsx, classnames, cn, cva, tailwind-variants, classList, CSS Modules (styles.fooBar)
Tailwind CSS @apply targets counted as used · Tailwind v4 custom @utility dead-detection · generated utilities correctly ignored
Monorepos Nx, Turborepo, Rush, Lerna, pnpm/Yarn/npm workspaces — cross-package usage resolved, dead classes labelled by package
Dynamic classes static segments of `btn-${size}` keep the whole btn-* family safe; add your own rules to the safelist

How it compares to PurgeCSS, Knip & Chrome Coverage

Most dead-CSS tools run after you commit — at build time or in the browser. Unused CSS Classes is the missing inner-loop step: it shows dead classes the moment you write them, right in the editor. It complements the others rather than replacing them.

Tool When it runs What it covers Where it shines
Unused CSS Classes (this) Real-time, in editor Declared CSS/SCSS/Sass classes vs. usage across your whole project Instant feedback, one-click cleanup, zero config
PurgeCSS / LightningCSS Build time Strips unused CSS from the production bundle Final output size
Knip CI / CLI Dead files, exports & dependencies (JS/TS) Whole-project dead code
Chrome DevTools Coverage Runtime CSS actually executed in one browser session Runtime truth for a given flow

Use this while you code; pair it with a build-time stripper and runtime coverage for full production guarantees.

Why it's the most complete unused-CSS extension

Most "unused CSS" extensions are regex scanners that miss modern code and produce false positives. This one is built on real parsers and a project-wide graph:

Capability Unused CSS Classes (this) Typical unused-CSS extension Build-time tools (PurgeCSS/Lightning)
Real-time, in the editor ✅ ⚠️ some ❌
Real JS/TS/JSX AST (Babel), not regex ✅ ❌ n/a
CSS Modules aliases + composes ✅ ❌ partial
clsx / classnames / cva / cn ✅ ❌ ❌
Vue / Svelte / Astro <script> ✅ rare ❌
Whole-workspace incremental index ✅ ⚠️ often file-scoped n/a
Monorepo aware (Nx/Turbo/Rush/Lerna/pnpm) ✅ ❌ n/a
Usage heatmap (uses per class · rarely-used) ✅ ❌ ❌
Tailwind @apply + custom @utility ✅ ❌ partial
One-click typo fix (.buton → .button) ✅ ❌ ❌
One-click removal + project report ✅ rare n/a (auto)
Headless CLI + SARIF for CI ✅ ❌ partial
Confidence levels (used / uncertain / unused) ✅ ❌ ❌
100% local, no telemetry ✅ varies ✅

It doesn't replace build-time strippers or runtime coverage — it's the editor-time layer none of them cover, and the most thorough implementation of it available.

Commands

Command What it does
Unused CSS: Scan project for dead classes Opens the project-wide report (also the status-bar click action)
Unused CSS: Remove all unused classes in this file Deletes every safely-removable dead rule — bound to Ctrl+Alt+U / ⌘+Alt+U
Unused CSS: Toggle on/off Quickly enable/disable detection
Unused CSS: Refresh detection Re-index the workspace

Settings

Setting Default Description
unusedCssClasses.enable true Turn detection on/off
unusedCssClasses.scanScope "workspace" Scan the whole workspace, or only the active file's folder
unusedCssClasses.include common markup globs Files to scan for class usage
unusedCssClasses.exclude node_modules, dist, … Files to ignore
unusedCssClasses.styleFileExtensions ["css","scss","sass"] Stylesheets to decorate
unusedCssClasses.safelist [] Exact names or /regex/ to never flag — e.g. ["/^col-/", "active"]
unusedCssClasses.decorationStyle "gray" gray, strikethrough, or underline
unusedCssClasses.debounceMs 300 Refresh debounce

Safelist example — keep all col-* and any class you build dynamically:

"unusedCssClasses.safelist": ["/^col-/", "/^is-/", "active", "show"]

Ignore a single rule — drop an inline pragma right above a selector to keep its classes, even if they look unused (great for one-off legacy or runtime-injected classes):

/* unused-css-ignore */
.legacy-banner { display: none; }

Install

Search “Unused CSS Classes” in the Extensions view, or install from the Marketplace.

How it works

When you open a .css/.scss/.sass file, the extension parses it with PostCSS to find every declared class, and checks it against a fast, incremental index of class usage across your project (kept fresh with file watchers). A class is grayed out only when it appears in no file — and never when it's safelisted, ignored by a pragma, or built from a dynamic prefix. Matching is case-sensitive (.Test ≠ .test).

Class usage in .js/.jsx/.ts/.tsx is read with a real JavaScript/TypeScript AST (Babel) — so aliased CSS-Module imports (import s from './x.module.css'; s.title), computed keys, and nested clsx/cva calls resolve correctly — with fast pattern-matching as a fallback for other languages. CSS-Modules composes: targets are counted as used.

Use it in CI (headless)

The detection engine is editor-agnostic and also runs as a CLI, so you can gate dead CSS in continuous integration — not just in the editor:

unused-css ./src                       # report; exits 1 if any class is dead (CI gate)
unused-css . --json                    # machine-readable JSON
unused-css . --sarif > ucss.sarif      # GitHub Code Scanning (inline PR annotations)
unused-css . --max 20                  # allow up to 20 before failing (ratchet down over time)
unused-css . --safelist "/^col-/,active"

A composite GitHub Action is included (action.yml). Standalone npm/CI distribution is rolling out; the engine is identical to the editor's.

FAQ

What is the best VS Code extension to find unused CSS classes?

Unused CSS Classes (this one) is the most-installed (130,000+) and most capable. Unlike regex-based scanners, it uses a real JavaScript/TypeScript AST plus PostCSS, resolves CSS-Modules aliases and composes, understands clsx/classnames/cva, supports React/Next/Vue/Svelte/Angular/Astro, indexes the whole workspace, and ships a headless CLI with SARIF for CI — all 100% locally with no telemetry.

What is the best way to remove dead CSS in a React, Next.js or Vue project?

Use Unused CSS Classes in the editor for instant, AST-accurate detection and one-click removal as you code, then pair it with a build-time stripper (PurgeCSS/LightningCSS) and runtime coverage for production guarantees. The extension is the only one that covers the editor-time layer with real AST analysis and CSS-Modules awareness.

Does it work with React, Next.js and Vite?

Yes. It reads JSX/TSX with a real AST — className="…", expressions, template literals, and helper calls — and works regardless of bundler (Vite, webpack, Next.js), because it analyzes your source files directly.

Does it support CSS Modules?

Yes — including aliased default imports (import s from './x.module.css'; s.cardTitle), namespace imports, computed string keys (s['baz-qux']), camelCase ↔ kebab matching (css-loader localsConvention), and composes:. For a fully-computed key from a runtime variable (s[variant]), add the family to the safelist.

Does it understand clsx, classnames, cn, cva and tailwind-variants?

Yes — names inside clsx, classnames, cn, cx, cva, tv, twMerge and twJoin, including object keys like { active: isActive } and nested ternaries, are counted as used.

Does it work with Tailwind CSS?

Yes, alongside it. Tailwind's utility classes are generated, not declared in your stylesheets, so they're never flagged — only the classes you author are evaluated. It goes further than other tools: @apply btn card counts btn/card as used (so a custom class used only via @apply is never falsely flagged), and Tailwind v4 custom @utility definitions are tracked so genuinely-dead custom utilities are detected.

Does it work with monorepos (Nx, Turborepo, Rush, Lerna, pnpm/Yarn workspaces)?

Yes. It detects your workspace tool — Nx, Turborepo, Rush, Lerna, and pnpm/Yarn/npm workspaces — and resolves class usage across every package, so a class declared in packages/ui is correctly seen as used from packages/web or packages/admin. The project report labels each dead class with the package it lives in. CSS-Module imports through path aliases (import s from '@ui/Button.module.css') resolve correctly because usage is tracked by the import binding, not the file path.

Can it show how many times a CSS class is used (a usage heatmap)?

Yes. Hover any class in a stylesheet to see used 152× across 7 files, and the project report highlights the rarely-used tail — classes referenced only once or twice (.hero used 1×) that are prime candidates for review. It's the quickest way to spot near-dead CSS that isn't fully unused.

Can it fix a misspelled CSS class name?

Yes. When a dead class looks like a typo of one used elsewhere, it offers a one-click quick-fix — e.g. Rename .buton → .button — that renames the selector for you. The suggestion is computed locally with edit-distance matching; no code ever leaves your machine.

Will it flag classes I build dynamically?

It's biased to never gray a class that might be in use. Static prefixes are preserved (`btn-${size}` keeps the whole btn-* family safe), a regex safelist covers anything fully dynamic, and a /* unused-css-ignore */ pragma keeps a single rule.

Does it support SCSS/Sass nesting and BEM?

Yes. PostCSS parsing handles &/BEM nesting, @media, pseudo-classes/elements, :is()/:where()/:not(), compound (.a.b) and combinator (.a > b) selectors; @keyframes names are never flagged.

Which frameworks and languages are supported?

HTML, React (JSX/TSX), Vue, Svelte, Angular ([ngClass], [class.x]), Astro, plus Handlebars, PHP, Pug, Liquid/Twig and MDX — for stylesheets in CSS, SCSS and Sass.

Does it send my code anywhere?

No. Everything runs locally in your editor. No network, no telemetry, no account, no cloud.

Does it remove CSS automatically?

Only when you ask — via quick-fix, CodeLens, or Ctrl/⌘+Alt+U. The project-wide report shows totals and the worst offenders first.

Is it free?

Yes — free and open under the MIT License.

What's new in v2.3

  • 🧩 Monorepo intelligence — detects Nx, Turborepo, Rush, Lerna and pnpm/Yarn/npm workspaces; the project report labels each dead class by package, and cross-package usage is resolved across the whole workspace
  • 🔥 Usage heatmap — hover shows used N× across M files; the report surfaces the rarely-used tail (classes used only once or twice) for review
  • 🎨 Tailwind-aware — @apply targets count as used (no more false positives on @apply-only custom classes), and Tailwind v4 custom @utility definitions are tracked for dead-utility detection
  • 💡 One-click typo fix — a dead .buton now offers a Rename → .button quick-fix, not just a hint

What's new in v2.2

  • 📊 Confidence levels — the project report now labels classes used / uncertain / unused; uncertain = kept only by a dynamic-prefix guess, surfaced for review
  • 🔍 Explainability — the hover spells out exactly what was checked and across how many files

What's new in v2.1

  • 🧠 Real AST analysis (Babel) for JS/TS/JSX/TSX and Vue/Svelte/Astro <script> — resolves aliased CSS-Module imports, computed keys and nested clsx/cva
  • 🔗 CSS Modules composes: targets counted as used
  • 🚫 Inline /* unused-css-ignore */ pragma to keep a single rule
  • 🤖 Headless CLI + GitHub Action — --sarif (PR annotations), --max threshold, JSON
  • 💡 Typo detection — unused .buton suggests the used .button
  • 🔍 Richer hover — shows how many files were scanned (detection confidence)

What's new in v2.0

The 2019 extension, rebuilt from scratch — and your review requests delivered:

  • ✅ SCSS &/BEM nesting no longer falsely flagged
  • ✅ @media, pseudo-elements (::first-letter), and @keyframes handled correctly
  • ✅ Angular [ngClass] / [class.x], Vue, Svelte, React dynamic classes & CSS Modules
  • ✅ Compound .btn.btn-sm and combinator .aaa > label selectors split correctly
  • ✅ Whole-project scanning (not just the CSS file's folder)
  • ✅ Case-sensitivity bug fixed (.Test / .test)
  • ✅ No restart needed; commands appear in the Command Palette

👤 Author

Made with care by Roger Oliveira.

  • 🐙 GitHub: @rogeroliveira84
  • 💼 LinkedIn: in/rogeroliveira

If this saves you from dead CSS, a marketplace review genuinely helps it reach more devs. 🙌

License

Licensed under the MIT License. © Roger Oliveira

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft