PostCSS PurgeCSS is a PostCSS plugin that integrates PurgeCSS functionality into PostCSS build pipelines, enabling developers to automatically remove unused CSS selectors from stylesheets during the build process. The plugin analyzes HTML, JavaScript, Vue, and other content files to identify which CSS selectors are actually used, then removes unused selectors to dramatically reduce CSS bundle sizes.
npm install -D @fullhuman/postcss-purgecss postcss// CommonJS
const purgeCSSPlugin = require('@fullhuman/postcss-purgecss');
// ES Modules (default import)
import purgeCSSPlugin from '@fullhuman/postcss-purgecss';
// ES Modules (named export)
import { purgeCSSPlugin } from '@fullhuman/postcss-purgecss';For TypeScript projects, you can also import types:
import purgeCSSPlugin, { UserDefinedOptions } from '@fullhuman/postcss-purgecss';
// Import additional types from the main purgecss package
import type {
RawContent,
ExtractorFunction,
ComplexSafelist,
UserDefinedSafelist
} from 'purgecss';const postcss = require('postcss');
const purgeCSSPlugin = require('@fullhuman/postcss-purgecss');
// Basic configuration
const result = await postcss([
purgeCSSPlugin({
content: ['./src/**/*.html', './src/**/*.js', './src/**/*.vue'],
fontFace: true,
keyframes: true
})
]).process(css, { from: 'input.css' });
console.log(result.css);The main plugin function that creates a PostCSS plugin instance for removing unused CSS.
/**
* PostCSS Plugin for PurgeCSS
* @param opts - PurgeCSS configuration options
* @returns PostCSS plugin instance with postcssPlugin: "postcss-purgecss"
*/
function purgeCSSPlugin(opts: UserDefinedOptions): {
postcssPlugin: "postcss-purgecss";
OnceExit(root: postcss.Root, helpers: postcss.Helpers): Promise<void>;
};
// Plugin properties
purgeCSSPlugin.postcss = true; // PostCSS 8 compatibility flagUsage Examples:
// Basic usage with content files
postcss([
purgeCSSPlugin({
content: ['./src/**/*.html', './src/**/*.js']
})
])
// Advanced configuration
postcss([
purgeCSSPlugin({
content: ['./src/**/*.html'],
safelist: ['button', 'btn-*', /^nav-/],
blocklist: ['unused-class'],
fontFace: true,
keyframes: true,
variables: true
})
])The plugin supports a contentFunction option that allows dynamic content selection based on the CSS source file being processed.
/**
* Dynamic content function for file-specific content analysis
* @param sourceFile - The CSS source file being processed
* @returns Array of content files or raw content to analyze
*/
type ContentFunction = (sourceFile: string) => Array<string | RawContent>;Usage Example:
purgeCSSPlugin({
contentFunction: (sourceFile) => {
// For component CSS files, only analyze the corresponding template
if (sourceFile.includes('component.css')) {
return [sourceFile.replace('.css', '.html')];
}
// For global CSS, analyze all templates
return ['./src/**/*.html'];
}
})The plugin accepts all PurgeCSS options except css (handled by PostCSS) with the addition of contentFunction.
interface UserDefinedOptions extends Omit<PurgeCSSUserDefinedOptions, "content" | "css"> {
content?: Array<string | RawContent>;
contentFunction?: (sourceFile: string) => Array<string | RawContent>;
extractors?: Array<Extractors>;
safelist?: UserDefinedSafelist;
blocklist?: StringRegExpArray;
skippedContentGlobs?: Array<string>;
fontFace?: boolean;
keyframes?: boolean;
variables?: boolean;
rejected?: boolean;
dynamicAttributes?: string[];
}Key Options:
content: Array of file paths or globs to analyze for CSS usagecontentFunction: Function that returns content files based on CSS source fileextractors: Custom extractors for different file typessafelist: CSS selectors to preserve (strings, regex, or complex object)blocklist: CSS selectors to force removefontFace: Remove unused @font-face ruleskeyframes: Remove unused @keyframes animationsvariables: Remove unused CSS custom propertiesrejected: Report removed selectors as PostCSS messagesThe safelist option provides flexible control over which CSS selectors to preserve. This uses the same safelist configuration as the main PurgeCSS package.
Usage Examples:
// Simple safelist
purgeCSSPlugin({
content: ['./src/**/*.html'],
safelist: ['button', 'btn-primary', /^nav-/]
})
// Complex safelist
purgeCSSPlugin({
content: ['./src/**/*.html'],
safelist: {
standard: ['button', 'btn-primary'],
deep: [/^nav-/],
greedy: [/^modal/],
variables: ['--primary-color'],
keyframes: ['fadeIn']
}
})The plugin supports analyzing raw content directly instead of only files, using the RawContent interface from the main PurgeCSS package.
Usage Example:
purgeCSSPlugin({
content: [
'./src/**/*.html',
{
raw: '<div class="header">Content</div>',
extension: 'html'
}
]
})Configure custom content extractors for different file types using the extractor interfaces from the main PurgeCSS package.
Usage Example:
purgeCSSPlugin({
content: ['./src/**/*.vue'],
extractors: [
{
extensions: ['vue'],
extractor: (content) => {
// Custom Vue.js extractor logic
const matches = content.match(/class="([^"]*)"/g) || [];
return matches.map(match => match.replace(/class="|"/g, '').split(' ')).flat();
}
}
]
})The plugin integrates seamlessly with PostCSS pipelines and other PostCSS plugins.
With PostCSS CLI:
// postcss.config.js
module.exports = {
plugins: [
require('@fullhuman/postcss-purgecss')({
content: ['./src/**/*.html']
})
]
}With Webpack:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('@fullhuman/postcss-purgecss')({
content: ['./src/**/*.html', './src/**/*.js']
})
]
}
}
}
]
}
]
}
}The plugin requires configuration options and will throw an error if none are provided.
// This will throw an error
postcss([purgeCSSPlugin()]); // Error: PurgeCSS plugin does not have the correct options
// Correct usage
postcss([purgeCSSPlugin({ content: ['./src/**/*.html'] })]);The plugin executes during the PostCSS OnceExit phase, after all other transformations are complete. This ensures that PurgeCSS sees the final CSS structure before purging unused selectors.
// Plugin execution order in PostCSS pipeline
postcss([
require('autoprefixer'), // Runs first
require('cssnano'), // Runs second
purgeCSSPlugin({ // Runs last (OnceExit)
content: ['./src/**/*.html']
})
])The plugin automatically loads configuration from purgecss.config.js if present, with explicit options taking precedence.
// purgecss.config.js
module.exports = {
content: ['./src/**/*.html'],
safelist: ['btn', 'btn-primary'],
fontFace: true,
keyframes: true
}
// Plugin usage - will merge with config file
purgeCSSPlugin({
rejected: true // This will be added to config file options
})When the rejected option is enabled, the plugin reports removed selectors as PostCSS messages with type "purgecss".
const result = await postcss([
purgeCSSPlugin({
content: ['./src/**/*.html'],
rejected: true
})
]).process(css);
// Access removal reports
result.messages.forEach(message => {
if (message.type === 'purgecss') {
console.log(message.text); // Lists purged selectors
}
});// Main configuration interface specific to this plugin
interface UserDefinedOptions extends Omit<PurgeCSSUserDefinedOptions, "content" | "css"> {
content?: Array<string | RawContent>;
contentFunction?: (sourceFile: string) => Array<string | RawContent>;
}
// Re-exported types from main purgecss package
type RawContent<T = string> = import('purgecss').RawContent<T>;
type UserDefinedSafelist = import('purgecss').UserDefinedSafelist;
type ComplexSafelist = import('purgecss').ComplexSafelist;
type Extractors = import('purgecss').Extractors;
type ExtractorFunction<T = string> = import('purgecss').ExtractorFunction<T>;
type ExtractorResult = import('purgecss').ExtractorResult;
type ExtractorResultDetailed = import('purgecss').ExtractorResultDetailed;
type StringRegExpArray = import('purgecss').StringRegExpArray;