o
odin.langpkg.dev
packages / library / unused-css

unused-css

d6bf230library

Find and remove unused css

Unlicense · updated 3 months ago

uncss

Find and remove unused CSS classes across a project.

Install

./build.sh

Requires Odin in PATH.

Usage

uncss [all] [flags]

Report mode (default) — prints unused classes, no files modified:

uncss
uncss --json

Apply mode — rewrites CSS files, backups written as .bak:

uncss all
uncss all --no-backup --yes

Flags

Flag Default Description
--ext=<list> .css,.less,.scss,.sass CSS file extensions
--markup-ext=<list> .html,.htm,.jsx,.tsx,.vue,.svelte,.astro,.php,.erb,.hbs,.mustache,.twig,.ejs Markup file extensions
--ignore=<list> node_modules,dist,build,.git,.next,vendor,target Directory names to skip
--no-backup Skip .bak backup in apply mode
--json Machine-readable JSON output
--yes, -y Skip confirmation prompt
-h, --help Show help

Output (report mode)

path/to/file.css:12:1  .unused-class
path/to/other.css:34:5 .another-class

3 unused class(es) across 2 file(s)

How it works

  1. Walk project from CWD, collect .css/.less/.scss/.sass and markup files.
  2. Scan markup for class= / className= attribute values — build a "used classes" set.
  3. Parse CSS: tokenize selector lists, extract .classname tokens with positions.
  4. Diff: classes in CSS not found in markup = unused.
  5. Report or remove.

Safety

  • Files containing @tailwind or @apply are skipped (Tailwind generates classes dynamically).
  • Rules containing &, #{, @include, @mixin, @extend are skipped (SCSS/LESS risk).
  • Only pure class selectors (e.g. .foo, .foo .bar, .foo:hover) are removed; selectors with tag names, IDs, or attribute selectors are kept.
  • Apply mode writes .bak backups by default.

Limitations (V1)

  • Dynamic classes (`btn-${variant}`) → false positives (class appears unused but isn't).
  • SCSS/LESS variables and mixins not resolved.
  • CSS Modules hash names not supported.
  • CSS-in-JS (styled-components, emotion) not scanned.