How UnCSS Works
UnCSS employs a sophisticated process to analyze your web pages and stylesheets to determine which CSS is actually in use. Understanding this process can help you use the tool more effectively and troubleshoot any issues that arise.
The Core Process
UnCSS follows four main steps:
1. HTML Loading & JavaScript Execution
First, UnCSS loads your HTML files into a virtual DOM environment powered by jsdom. This is not just a simple HTML parser; jsdom
emulates a web browser's environment, complete with window
and document
objects.
Crucially, it executes the JavaScript found on the page that runs during the initial page load. This allows UnCSS to detect CSS classes and styles that are added, removed, or modified dynamically by your scripts. The DOM that UnCSS analyzes is the one that exists after this initial script execution.
2. Stylesheet Parsing
Next, UnCSS discovers all relevant stylesheets. It finds <link rel="stylesheet">
tags in your HTML and can also be given a list of stylesheets directly via the stylesheets
option. It then reads these files and parses them using PostCSS. This converts the raw CSS text into an Abstract Syntax Tree (AST), which is a structured, tree-like representation of the CSS rules, selectors, and properties.
3. Selector Filtering
This is the core of UnCSS's logic. It iterates through every single CSS rule from the AST. For each selector in a rule (e.g., .my-class
, #my-id > p
), UnCSS uses the document.querySelector
method in the jsdom
environment to check if any element on the page matches that selector.
- If
document.querySelector('your-selector')
returns an element, the selector is considered used. - If it returns
null
, the selector is considered unused.
A CSS rule is kept if at least one of its selectors is found on the page.
4. Clean CSS Regeneration
After checking all selectors, UnCSS filters the PostCSS AST, removing any rules that were found to be completely unused. The modified, lightweight AST is then converted back into a minified CSS string, which is the final output.
Limitations
While powerful, this process has some inherent limitations that are important to be aware of:
- No User Interaction: UnCSS does not simulate user interactions like clicking buttons, hovering over elements, or scrolling. If your JavaScript adds a class like
.is-open
only when a user clicks a menu button, UnCSS will not see it and will likely remove the associated styles. This is the primary use case for theignore
option. - Non-HTML Files: UnCSS cannot directly process server-side templates (e.g., PHP, ERB, Handlebars). It needs rendered HTML to work. The recommended approach is to either generate static HTML pages from your templates for UnCSS to scan, or run a local development server and point UnCSS to the live URLs.
- Pseudo-elements & Pseudo-classes: Certain pseudo-classes like
:hover
,:focus
, and:active
, and pseudo-elements like::before
and::after
cannot be directly queried in the DOM. UnCSS has special logic to handle these: it checks for the existence of the base selector (e.g., for.button:hover
, it checks if.button
exists) and preserves the rule if it does. See Ignoring Selectors for more details.