How It Works
PurifyCSS uses a static analysis approach to determine which CSS selectors are used in your project. This section provides a deeper look into the process.
The Purification Process
The process can be broken down into four main steps:
1. Content Aggregation and Analysis
First, PurifyCSS gathers all the content you've provided (via file paths, globs, or direct strings).
- It reads and concatenates all HTML, PHP, template files, etc., into a single string.
- For JavaScript files, it goes a step further. It uses UglifyJS to parse and compress the code. This is a crucial step because it resolves simple string concatenations. For example, a dynamic class like
'button-' + 'active'
becomes'button-active'
, making it discoverable. - Finally, it extracts every word-like sequence (
/[a-z]+/g
) from the entire aggregated content string and stores them in a Set for fast lookups.
2. CSS Parsing
Next, PurifyCSS reads and concatenates all provided CSS files. It then uses the rework
library to parse the CSS into an Abstract Syntax Tree (AST). This tree structure represents all the rules, selectors, and properties in your CSS, making them easy to manipulate.
3. Selector Filtering
This is the core of the purification logic. The tool traverses the CSS AST and examines each rule.
- For each selector (e.g.,
.btn.btn-primary:hover
), it extracts all the meaningful words (in this case,btn
andbtn-primary
). It ignores pseudo-classes (:hover
), pseudo-elements (::before
), attribute selectors ([type="button"]
), and the universal selector (*
). - It then checks if every single word from the selector exists in the set of words gathered from the content in Step 1.
- If all words are found, the selector is considered "used" and is kept.
- If even one word is missing, the selector is removed from the rule.
4. AST Pruning and Output Generation
After filtering, some CSS rules may have no selectors left. These empty rules are removed from the AST. Similarly, @media
blocks that become empty after their child rules are removed are also pruned.
Finally, the modified, cleaned-up AST is converted back into a CSS string, which is either returned, written to a file, or passed to a callback.
Handling Dynamic Class Names
PurifyCSS is surprisingly effective at detecting class names that are constructed dynamically in JavaScript. Here are some examples of what it can find:
// Simple concatenation
var half = 'button-';
$(button).addClass(half + 'active'); // Detects 'button-active'
// Array join
var dynamicClass = ['button', 'active'].join('-'); // Detects 'button-active'
$(button).addClass(dynamicClass);
// React's classnames library
var classes = classNames({
'button-active': this.state.buttonActive
}); // Detects 'button-active'
By compressing the JavaScript first, many of these dynamic constructions are resolved into static strings, which are then easily found during the word extraction phase.