Optimize TailwindCSS by removing unused CSS classes

I've gushed about TailwindCSS on ironeko before. A couple of months into using it, I'm still discovering new tricks, and removing unused CSS to dramatically reduce network payload and optimize TailwindCSS is probably my favorite.

TailwindCSS is great, but...

What I didn't realise when first writing about this fantastic new framework was how many options for optimization it offered. Here's the thing: Tailwind is fantastic, but it has thousands of lines of styles - one for almost every CSS property. This means that once you build your project, all that CSS, even the classes you didn't use, will end up in your final stylesheet.

TailwindCSS is almost 500kb in size, which in internet terms is a LOT. A big payload (i.e. a large total file-size) when loading your site can mean less mobile users, worse SEO, and less opportunity for your content to be seen.

Thankfully, because of the way TailwindCSS is built, it's easy to automatically check which classes you've used, and remove everything else from your final build. To give you an idea, here's how much it improved the payload for ironeko.

Optimize TailwindCSS with PurgeCSS

That's almost 1MB of difference.

Reduce Tailwind's filesize with PurgeCSS

PurgeCSS is a fantastic utility and, unlike many others, it's actually really straightforward. Here's how to use it.

0. On Tailwind 1.4

Update: Since writing this article Tailwind has been updated to version 1.4. While the following article ant tutorial still works, Tailwind now also provides a built-in PurgeCSS functionality.

You can simply add the following to your tailwind.config.js file.

module.exports = {
  purge: {
    content: ["./src/**/*.html"],
    options: {
      whitelist: ["bg-red-500", "px-4"]
    }
  }
};

1. Install PurgeCSS

npm install @fullhuman/postcss-purgecss --save-dev

2. Set up its config files

You should already have a postcss.config.js file from your Tailwind installation. Simply change it to the following:

// postcss.config.js
const purgecss = require("@fullhuman/postcss-purgecss")({
  // Here you should add the files to check for the classes you've used. This is how it looks for mine, I check all my components and pages.
  content: ["./pages/*.js", "./components/*.js"],

  // Include any special characters you're using in this regular expression
  defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
});

module.exports = {
  plugins: [
    require("tailwindcss"),
    require("autoprefixer"),
    ...(process.env.NODE_ENV === "production" ? [purgecss] : [])
  ]
};

We've set this up to only run when we actually build our project. This means that during development we won't need to wait too long for our project to compile.

Edge cases and fixes

While the above should work for 99% of cases, there are still a few things to look out for.

In ironeko's case, for example:

  • Since I use NextJS I don't actually use a body or html tag in my code.
  • Since I dynamically generate my content, I don't use many other html tags such as li, ul, img and others.

This means any CSS for these will get removed. This can be easily fixed by whitelisting. Here's a couple of different methods to do so.

Simple Whitelisting

const purgecss = require("@fullhuman/postcss-purgecss")({
  whitelist: ["body", "html", "img", "video", "iframe"]
});

This will match the exact class. Fairly straightforward.

Whitelist Patterns

Patterns allow us to match any class that includes the string provided. This is great for library-specific CSS. In my case I used it to whitelist nprogress's styles.

const purgecss = require("@fullhuman/postcss-purgecss")({
  whitelistPatterns: [/nprogress/]
});

CSS Whitelisting

The last, and least pretty, way to exclude styles is adding the purgeCSS exclusive comment /* purgecss ignore */ above the class to be excluded.

/* purgecss ignore */
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
	background: #272822;
}

It's not my favourite, but it does have its uses.

Conclusion

No matter what your site does, optimising it to have the lowest payload possible should be one of your top priorities. It might seem like a lot of work but having a fast and responsive site will pay off in the long run.

PurgeCSS helps automatise a lot of this tedious process, making TailwindCSS an even better framework.