Editor’s note: This guide to removing unused CSS code with PurgeCSS was last updated by Elijah Agbonze on 9 June 2023 to reflect recent changes to PurgeCSS. This update also includes new sections on using PurgeCSS with React and Vue.js and a deeper explanation of PurgeCSS. To explore more CSS optimization techniques, visit our guide to the best practices for minifying CSS.
CSS frameworks are collections of style sheets that are preprepared in advance and come ready to use. Developers opt for CSS frameworks to deliver digital experiences in a more intuitive, efficient, and standards-compliant manner.
However, CSS frameworks can also cause problems. It’s unlikely that you’ll use every feature offered in a CSS framework, meaning unused code will be leftover in your final application. Unused code can result in a larger file size, harm performance, make it easy to lose track of each item, and cause optimization problems.
Removing unnecessary code will make your website load faster because the browser will request and parse less code. In this tutorial, we’ll explore PurgeCSS, a tool for removing unused CSS code. With PurgeCSS as a part of our development workflow, we can easily remove unused CSS, resulting in smaller CSS files and improving our application overall.
Jump ahead:
When using CSS frameworks like Tailwind CSS and Bootstrap, we often find ourselves with CSS codes not used in our project. This can play a huge role in generating performance issues like longer page load times for your application.
For example, Tailwind uses PurgeCSS to remove unused CSS from final builds automatically. Netflix Top 10 uses Tailwind on its entire website and only requires 6.5kB for the CSS file. The CSS file would be ten times the final build size without removing unused CSS.
This is because, during development, you use classes or make declarations that you wind up not using. This isn’t an error on the developer’s part. These things are bound to happen. So, the more classes are being generated (as in Tailwind, for example) for just trying out a design you have in mind, the more your CSS file grows.
PurgeCSS is a tool used to remove unused CSS. It is very often useful for optimizing your applications for production. When you use CSS frameworks like Bulma, Bootstrap, or Tailwind, you’ll find yourself with lots of unused CSS. While this is good during development, it can be a real performance issue for production.
This is where PurgeCSS comes in. It analyzes your content as well as your CSS files to determine which styles are unused and removes them instantly. PurgeCSS works with the most common JavaScript libraries/frameworks like Vue.js, React, Gatsby, and more.
While PurgeCSS is not the only tool for removing unused CSS, it stands out thanks to its modularity, ease of use, and wide range of customization options. Modularity enables developers to create module extractors for specific use cases and frameworks. An extractor is a function that reads the contents of a file and extracts a list of CSS selectors that are used.
PurgeCSS provides a very reliable default extractor that can work with a wide range of file types. However, by default, PurgeCSS ignores unused CSS code containing special characters like @
,:
, and /
. Therefore, PurgeCSS may not fit the exact file type or CSS framework that you’re using.
Additionally, PurgeCSS has a wide range of options that allow you to customize its behavior according to your needs. For example, PurgeCSS includes options for fontFace
, keyframes
, extractors
, css
, and more. Customization can improve the performance and efficiency of PurgeCSS.
And finally, PurgeCSS is very easy to get started with and includes thorough documentation. At the time of writing, PurgeCSS is loved by developers, with 900k+ weekly downloads on npm and 7.4k GitHub stars.
PurgeCSS, which works best for production builds, and analyzes your content and CSS and removes the unused styles. The contents indicate the page(s) that use your styles. Running PurgeCSS during development can be unnecessary. This is because during development, you’d often create unused styles, and it would mean you’d have to run PurgeCSS every time.
Instead, you can run it for just the production build. This way, you won’t have to recreate removed styles. So, when your app is ready for production, you can run PurgeCSS once. Before we jump into using PurgeCSS with popular libraries/frameworks, let’s take a look at how it works with vanilla JavaScript. Check out the following code:
(async () => { const purgecss = await new PurgeCSS().purge({ content: ['index.html'], css: ['style.css'], }); console.log(purgecss); })();
The code above is a simple example of using PurgeCSS. We specified index.html
as one of the contents and style.css
as one of the CSS. We can have more content and CSS files; interestingly, the contents are not limited to HTML files (we will see more later). The example above returns an array of the purged styles.
There are more options other than just content
and css
for specifying exactly what you want it to do and how you want it to do it; we will take a look at that in a moment. The example above can be used for any vanilla JavaScript project. To use it, you need to have a separate JavaScript file you will run once to remove unused styles.
So, if your app is ready to be built and sent, create the new js
file, paste the code, and run it. Right now, we are only logging purgecss
, but you can change that. And, instead of logging the result, you’d have the purged styles replace the current styles:
const { PurgeCSS } = require('purgecss'); const fs = require('fs'); (async () => { const purgecss = await new PurgeCSS().purge({ content: ['index.html'], css: ['style.css'], }); fs.writeFileSync('style.css', purgecss[0].css); })();
As you can see, replacing the purged styles with the current styles is way easier with JavaScript frameworks/libraries.
PurgeCSS is compatible with popular JavaScript libraries/frameworks like React, Vue, Gatsby, Next.js, Nuxt.js, etc. But, in this tutorial, we will only take a look at using PurgeCSS with React and Vue.
First, open up your terminal and run the following command to install React using Create React App:
npx create-react-app purgecss-react-tutorial
Next, move into the purgecss-react-tutorial
directory we just created:
cd purgecss-react-tutorial
Now, go ahead and install PurgeCSS and its dependencies:
npm i --save-dev @fullhuman/postcss-purgecss
Open your App.js
file and paste the following code:
import "./App.css"; function App() { return <div className="App"></div>; } export default App;
In the code above, we created a functional component called App
and returned a div
with a classname
of App
. Our App.css
is left untouched, so it contains the following unused CSS code:
.App { text-align: center; } .App-logo { height: 40vmin; pointer-events: none; } @media (prefers-reduced-motion: no-preference) { .App-logo { animation: App-logo-spin infinite 20s linear; } } .App-header { background-color: #282c34; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); color: white; } .App-link { color: #61dafb; } @keyframes App-logo-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
Open up your package.json
file and add the following line under scripts
:
"postbuild": "purgecss --css build/static/css/*.css --content build/index.html build/static/js/*.js --output build/static/css"
post
is a prefix that can be added to any npm script and will automatically run when you run the main script. In our case, postbuild
runs after the build
script is executed. The command executed by postbuild
contains three options. The --css
option specifies what CSS files PurgeCSS should process.
It can be an array of filenames or globs. The --content
option is similar to the --css
option, specifying what content should be analyzed by PurgeCSS. The --output
option specifies what directory you should write the purified CSS files to. By default, it places the result in the console.
In essence, the command executed by postbuild
does the following:
build/static/css
build/static/css
Now, all you have to do is run npm run build
to run the build of your React application. To confirm if you were successful, open the CSS file in build/static/css
. The output looks like the code below, containing only the used CSS:
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; margin: 0; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, Courier New, monospace; } .App { text-align: center; } @-webkit-keyframes App-logo-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } to { -webkit-transform: rotate(1turn); transform: rotate(1turn); } } @keyframes App-logo-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } to { -webkit-transform: rotate(1turn); transform: rotate(1turn); } }
Again, you’re going to open a terminal window and run the following command to create a new Vue project. First, make sure you have Vue CLI installed:
npm install -g @vue/cli
Now, run the command below to create a Vue project:
vue create purgecss-vue-tutorial
Next, move into purge-css-vue-tutorial
and add PurgeCSS:
cd purgecss-vue-tutorial vue add @fullhuman/purgecss
This will generate a postcss.config.js
file, and in this file are your PurgeCSS configurations already set to suit your Vue app. You can always change these configurations to best fit your needs. We will see how to make these changes in the next section of this article.
But, we don’t have to update the configurations for this tutorial. The default config is enough to get PurgeCSS up and running for this project. So, now let’s update some contents of our app and see PurgeCSS at work in Vue. Head up to HelloWorld.vue
and replace the code there with the one below:
<template> <a href="#">Hello world</a> </template> <script> export default { name: 'HelloWorld', props: { msg: String, }, }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h3 { margin: 40px 0 0; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } span { color: red; } </style>
We’ve reduced the content and added some unused styles to it (for demonstration only). Now, let’s build our application to see the CSS in the final build of our app. In your terminal, run npm run build
, and wait for the build to complete. To confirm, open the CSS file in dist/css
, and you will find the output of the CSS containing only the used styles:
a[data-v-70cf4e96] { color: #42b983; } #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; }
So far, we’ve only seen three configuration options: content
, css
, and outline
, but more configuration options allow you to customize PurgeCSS.
Prior to PurgeCSS v2.0, unused fontfaces and keyframes code were removed by default. However, when these features were used incorrectly, the code would break. Unused fontfaces and keyframes code are now left untouched by default. You can change this default behavior by setting the keyframes and fontfaces options to true:
(async () => { const purgecss = await new PurgeCSS().purge({ content: ['index.html'], css: ['style.css'], keyframes: true, fontFaces: true, }); console.log(purgecss); })();
The configuration options can also be in a config file that is purgecss.config.js
:
// purgecss.config.js module.exports = { content: ['index.html'], css: ['style.css'], keyframes: true, fontFaces: true, } (async () => { const purgecss = await new PurgeCSS().purge('./purgecss.config.js'); console.log(purgecss); })();
You can directly pass in the value of both content
and css
without linking a file to it as we’ve been doing. Here’s what that looks like:
// purgecss.config.js module.exports = { content: [ { raw: '<html><body><p>Hello world</p></body></html>', extension: 'html', }, ], css: [ { raw: 'p { color: red }', }, ], };
In some very rare cases, PurgeCSS may not be able to remove unused CSS or remove used CSS. In that case, you’d have to use a custom extractor. PurgeCSS relies on extractors to get the list of selectors used in a file.
There are packages that provide extractors for specific extensions. For example, purgecss-from-js is specific to .js
extensions. Using a specific extractor for an extension should provide the best accuracy:
// purgecss.config.js import purgeJs from 'purgecss-from-js' import purgeHtml from 'purgecss-from-html' const options = { content: ['index.html'], css: ['style.css'], extractors: [ { extractor: purgeJs, extensions: ['js'] }, { extractor: purgeHtml, extensions: ['html'] } ] } export default options
By default, your unused CSS variables are not removed. If you want to remove them, you’d have to specify variables
as true
in your purgecss.config.js
file:
module.exports = { content: ['index.html'], css: ['style.css'], variables: true, }
You can indicate which selectors are safe to leave in the final CSS. We can accomplish this in two ways: the PurgeCSS option safelist
or the special CSS special comment. Using safelist
:
module.exports = { content: ['index.html'], css: ['style.css'], safelist: ['random', 'button'], }
In this case, .random
, #random
, button
, .button
, and #button
will all be ignored and not removed by PurgeCSS. You can take it to the next level using Regular expressions:
module.exports = { content: ['index.html'], css: ['style.css'], safelist: [/red$/, /^bg/], }
In this case, any selector that ends with red
(e.g., bg-red
, btn-red
) or that starts bg
(e.g., bg-blue
, bg-red
) will not be removed. By default, comments are not removed by PurgeCSS. Only special comments that are meant to customize the behavior of PurgeCSS are removed.
One common special set of comments is the ones used to specify which selectors are safe to leave in the final CSS:
/* purgecss start ignore */ h1 { color: pink; font-size: 2rem; } /* purgecss end ignore */
In this article, we explored PurgeCSS, a tool to remove unused CSS from your code, thereby reducing file size and improving optimization. We covered the major offerings of PurgeCSS, including its modularity, customization options, and ease of use.
Then, we reviewed the steps required to get started with PurgeCSS on React as well as Vue, and some configuration options to help customize PurgeCSS to fit our needs.
Even if you decide to use a CSS framework like Tailwind, Bootstrap, MaterializeCSS, or Foundation, PurgeCSS should work perfectly. I hope you enjoyed this article!
As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.
Modernize how you debug web and mobile apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn to build scalable micro-frontend applications using React, discussing their advantages over monolithic frontend applications.
Build a fully functional, real-time chat application using Laravel Reverb’s backend and Vue’s reactive frontend.
console.time is not a function
errorExplore the two variants of the `console.time is not a function` error, their possible causes, and how to debug.
jQuery 4 proves that jQuery’s time is over for web developers. Here are some ways to avoid jQuery and decrease your web bundle size.
6 Replies to "Guide to removing unused CSS code with PurgeCSS"
So what happens when you need the css features that has been purged?
Keep in mind that PurgeCSS doesn’t touch your source CSS files, just the ones that are output by the build process. So if you add new code that needs CSS rules that were previously purged, then the next time you build your app PurgeCSS will see that your code is using some new rules and will not purge them in that build.
In frameworks such as Angular, you can use scss which is complied down to css. Is there any way to achieve this on scss?
It doesn’t make sense to run it on SCSS because other SCSS files might be referencing your code dynamically elsewhere. You can transpile it to CSS, then run the process on CSS as part of your CI pipeline or have a local git hook to do so. It has the same effect.
Is that possible to use purgeCSS in angularjs version 1.5?
With Gulp i cant get it to work… dont get any error messages but the css is still there…