Controlling File Size
Strategies for keeping your generated CSS small and performant.
Using the default configuration, Tailwind CSS comes in at 58.1kb minified and gzipped.
Here are a few other popular frameworks for comparison:
Framework | Original Size | Minified | Gzip | Brotli |
---|---|---|---|---|
Tailwind | 477.6kb | 350.4kb | 58.8kb | 17.1kb |
Bootstrap | 187.8kb | 152.1kb | 22.7kb | 16.7kb |
Bulma | 205.6kb | 172.4kb | 23.0kb | 18.0kb |
Foundation | 154.1kb | 119.2kb | 15.9kb | 12.9kb |
Tachyons | 111.7kb | 71.8kb | 13.4kb | 7.5kb |
Semantic UI | 809.4kb | 613.8kb | 100.6kb | 77.8kb |
Materialize | 175.0kb | 138.5kb | 21.1kb | 17.1kb |
By comparison Tailwind definitely seems on the heavy side (although if you use Brotli instead of gzip it’s still very reasonable), but there are a number of strategies you can use to reduce this file size dramatically.
Removing unused CSS
Mozilla’s Firefox Send is built with Tailwind, yet somehow their CSS is only 13.1kb minified, and only 4.7kb gzipped! How?
They’re using Purgecss, a tool for removing CSS that you’re not actually using in your project. Purgecss is particularly effective with Tailwind because Tailwind generates thousands of utility classes for you, most of which you probably won’t actually use.
For example, Tailwind generates margin utilities for every size in your spacing scale, for every side of an element you might want to apply margin to, at every breakpoint you are using in your project. This leads to hundreds of different combinations that are all important to have available, but not all likely to be needed.
When using Purgecss with Tailwind, it’s very hard to end up with more than 10kb of compressed CSS.
Setting up Purgecss
In the future we may incorporate Purgecss directly into Tailwind, but for now the best way to use it in your project is as a PostCSS plugin.
To get started with Purgecss, first install @fullhuman/postcss-purgecss
:
# Using npm
npm install @fullhuman/postcss-purgecss
# Using yarn
yarn add @fullhuman/postcss-purgecss
Next, add it as the last plugin in your postcss.config.js
file:
// postcss.config.js
const purgecss = require('@fullhuman/postcss-purgecss')({
// Specify the paths to all of the template files in your project
content: [
'./src/**/*.html',
'./src/**/*.vue',
'./src/**/*.jsx',
// etc.
],
// Include any special characters you're using in this regular expression
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
})
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
...process.env.NODE_ENV === 'production'
? [purgecss]
: []
]
}
Note that in this example, we’re only enabling Purgecss in production. We recommend configuring Purgecss this way because it can be slow to run, and during development it’s nice to have every class available so you don’t need to wait for a rebuild every time you change some HTML.
Writing purgeable HTML
Purgecss uses "extractors" to determine what strings in your templates are classes. In the example above, we use a custom extractor that will find all of the classes Tailwind generates by default:
const purgecss = require('@fullhuman/postcss-purgecss')({
// ...
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
})
The way it works is intentionally very "dumb". It doesn’t try to parse your HTML and look for class attributes or dynamically execute your JavaScript — it simply looks for any strings in the entire file that match this regular expression:
/[A-Za-z0-9-_:/]+/g
That means that it is important to avoid dynamically creating class strings in your templates with string concatenation, otherwise Purgecss won’t know to preserve those classes.
Don’t use string concatenation to create class names
<div :class="text-{{ error ? 'red' : 'green' }}-600"></div>
Do dynamically select a complete class name
<div :class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
As long as a class name appears in your template in its entirety, Purgecss will not remove it.
Customizing the regular expression
In the example above, we use a regular expression that matches all of the non-standard characters Tailwind uses by default, like :
and /
.
If you are using any other special characters in your class names, make sure to update the regular expression to include those as well.
For example, if you have customized Tailwind to create classes like w-50%
, you’ll want to add %
to the regular expression:
- /[A-Za-z0-9-_:/]+/g
+ /[A-Za-z0-9-_:/%]+/g
Removing unused theme values
If you can’t use Purgecss for one reason or another, you can also reduce Tailwind’s footprint by removing unused values from your configuration file.
The default theme provides a very generous set of colors, breakpoints, sizes, margins, etc. to make sure that when you pull Tailwind down to prototype something, create a CodePen demo, or just try out the workflow, the experience is as enjoyable and fluid as possible.
We don’t want you to have to go and write new CSS because we didn’t provide enough padding helpers out of the box, or because you wanted to use an orange color scheme for your demo and we only gave you blue.
This comes with a trade-off though: the default build is significantly heavier than it would be on a project with a purpose-built configuration file.
Here are a few strategies you can use to keep your generated CSS small and performant.
Limiting your color palette
The default theme includes a whopping 93 colors used for backgrounds, borders, and text, all of which also have hover:
and focus
variants, as well as responsive variants at the five default screen sizes.
This means that by default, there are 4185 classes generated from this color palette out of 8271 classes total in the entire default build.
Very few projects actually need this many colors, and removing colors you don’t need can have a huge impact on the overall file size.
Here’s how using a smaller color palette affects the final size:
Colors | Original | Minified | Gzip | Brotli |
---|---|---|---|---|
93 (default) | 477.6kb | 350.4kb | 58.8kb | 17.1kb |
50 | 361.3kb | 260.3kb | 45.7kb | 13.9kb |
25 | 293.1kb | 207.2kb | 38.0kb | 12.2kb |
Removing unused breakpoints
Since almost every Tailwind utility is copied for every screen size, using fewer screen sizes can have a huge impact on the overall file size as well.
Here’s how defining fewer screens affects the output:
Breakpoints | Original | Minified | Gzip | Brotli |
---|---|---|---|---|
4 (default) | 477.6kb | 350.4kb | 58.8kb | 17.1kb |
3 | 380.9kb | 279.7kb | 47.4kb | 16.3kb |
2 | 284.2kb | 209.0kb | 36.0kb | 15.0kb |
1 | 187.5kb | 138.3kb | 24.5kb | 13.7kb |
If you only need 3 screen sizes and 35 colors, you’re down to 32.5kb after gzip (11.7kb after Brotli!) without changing anything else.
Disabling unused utilities and variants
If you don’t expect to need a certain utility plugin in your project at all, you can disable it completely by setting it to false
in the corePlugins
section of your config file:
// tailwind.config.js
module.exports = {
// ...
corePlugins: {
float: false
}
}
If you need a utility but don’t need the responsive versions, set its variants to an empty array to generate 80% fewer classes:
module.exports = {
// ...
variants: {
appearance: []
}
}
These are mostly small wins compared to limiting your color palette or using fewer breakpoints, but they can still add up.