Skip to content

Instantly share code, notes, and snippets.

@mattsacks
Last active August 21, 2023 08:00
Show Gist options
  • Save mattsacks/0a257ec2057f08c25aae820cd73a1019 to your computer and use it in GitHub Desktop.
Save mattsacks/0a257ec2057f08c25aae820cd73a1019 to your computer and use it in GitHub Desktop.
Purging CSS with CSS Modules

Tailwind.css and CSS Modules make a lovely pairing. You get to write things like:

/* In your styles.module.css file: */
.heading {
  composes:
    global(bg-primary)
    global(p-6)
    global(text-center)
    global(text-secondary);

  composes:
    global(md:flex)
    global(md:flex-1)
    global(md:flex-col)
    global(md:h-48)
    global(md:justify-center);
}
// In your component
import styles from "./styles.module.css";

export default function Heading() {
  // All of the global classes defined in styles.heading will be applied here:
  return <h1 className={styles.heading}>My cool heading</h1>;
}

With this approach, components can be written in a way that doesn't create any new CSS rules (besides a generated heading_[hash] placeholder).

The only downside is that Tailwind generates a lot of CSS. Luckily, that can be purged away with the following postcss.config.js:

const plugins = [
  "tailwindcss",
  "autoprefixer"
];

if (process.env.NODE_ENV === "production") {
  plugins.push([
    "@fullhuman/postcss-purgecss",
    {
      // Don't purge any styles found in the global stylesheets
      css: ["./styles/**/*.css"],

      // For all files found, only match potential CSS classnames on the
      // defaultExtractor:
      content: ["./**/*.jsx", "./**/*.tsx", "./**/*.module.css"],
      defaultExtractor: (content) => content.match(/[\w-/:]+(?<!:)/g) || []
    }
  ]);
}

module.exports = { plugins };

Keep in mind that this can be potentially slow, as the defaultExtractor function is run on every file's content that matches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment