Moeki Kawakami

Eliminating unused selectors from Sass

For CSS, there is

But what about Sass? You want to eliminate unused selectors not only from the built result, but also from the Sass source code.

I tried it. cc-kawakami/uchini: Find unused Sass codes

npm i -g uchini

("Uchini" is Japanese for unloading cargo from a ship that is about to sink.)

$ uchini ls --help
List CSS selectors usage

  $ uchini ls --scss <value> --content <value> [--output
    <value>] [--unusedOnly]

  --content=<value> (required) Path to content file
  --output=<value> Path to output file
  --scss=<value> (required) Path to CSS file
  --unusedOnly Unused selectors only

  List CSS selectors usage

  $ uchini ls --css path/to/css --content path/to/content --output path/to/output --unusedOnly
uchini ls --scss path/to/scss --content 'path/**/*.html' --output output.json


    "selector": ".header",
    "positions": [
    "selector": ".card",
    "positions": [

Internally we use the following.

First, compile Sass.

const compiled = sass.compile(scss, {
  style: 'compressed',
  sourceMap: true,
  logger: sass.Logger.silent

Then, the source-map creates a consumer.

const consumer = await new sourceMap.SourceMapConsumer(compiled.sourceMap)

Next, we identify the CSS selectors that are not being used by purgecss.

const rejectedCSS = await new PurgeCSS().purge({
  content: [content],
  css: [{ raw: css }],
  rejected: true

Then, the consumer can use the source map to traverse the Sass lines corresponding to a given line of CSS.

const position = this.consumer.originalPositionFor({
  line: 1, // since the source map is a single line in compressed
  column: startOfSelector

That's it.

Thank you for reading.

← Back to list