PostCSS plugin that detects and removes browser-specific CSS hacks based on target browser support
npx @tessl/cli install tessl/npm-stylehacks@7.0.0stylehacks is a PostCSS plugin that detects and removes browser-specific CSS hacks from stylesheets based on target browser support. It analyzes CSS declarations, rules, and other nodes to identify outdated browser hacks (like underscore hacks for IE6) and either removes them or warns about their presence in lint mode. The library integrates with browserslist to determine which hacks are still needed based on the browsers you need to support.
npm install stylehacksconst stylehacks = require('stylehacks');For TypeScript or ES modules:
import stylehacks from 'stylehacks';const postcss = require('postcss');
const stylehacks = require('stylehacks');
// Default mode - removes detected hacks
postcss([stylehacks()])
.process(css, { from: undefined })
.then(result => {
console.log(result.css); // CSS with hacks removed
});
// Lint mode - only warns about hacks
postcss([stylehacks({ lint: true })])
.process(css, { from: undefined })
.then(result => {
console.log(result.messages); // Array of warnings
});const postcss = require('postcss');
const stylehacks = require('stylehacks');
const css = 'h1 { _color: red; color: blue; }';
const root = postcss.parse(css);
root.walkDecls(decl => {
if (stylehacks.detect(decl)) {
console.log(`Found hack: ${decl.prop}: ${decl.value}`);
}
});stylehacks is built around a modular plugin architecture that systematically detects different types of browser-specific CSS hacks:
The plugin walks through all CSS nodes (declarations, rules, at-rules) and applies relevant detection plugins. Each plugin can either remove hacks (default mode) or emit warnings (lint mode) when hacks are detected.
stylehacks includes 12 specialized plugins for different hack types:
body:empty selector hacks (Firefox 2)html/**/selector hacks (IE6)html:first-child selector hacks (IE7)!important variants (various IE versions)*property: value hacks (IE5.5-7)_property: value hacks (IE6)@media \0screen hacks (IE8-9)@media \0screen\,screen\9 hacks (IE8)@media screen\9 hacks (IE8)property: value\9 hacks (IE6-8)* html selector hacks (IE6)selector\, hacks (IE6-7)Creates a PostCSS plugin instance that processes CSS to detect and handle browser hacks.
/**
* Creates a PostCSS plugin for detecting and removing CSS browser hacks
* @param opts - Configuration options
* @returns PostCSS plugin instance
*/
function stylehacks(opts?: Options): Plugin;
interface Options {
/** Enable lint mode - warnings only, no removal */
lint?: boolean;
/** Override browserslist configuration */
overrideBrowserslist?: string | string[];
/** Path for browserslist resolution */
path?: string;
/** Environment for browserslist */
env?: string;
/** Custom stats for browserslist */
stats?: any;
}Usage:
// Remove hacks (default behavior)
const plugin = stylehacks();
// Lint mode only
const lintPlugin = stylehacks({ lint: true });
// Custom browser support
const customPlugin = stylehacks({
overrideBrowserslist: ['> 1%', 'last 2 versions']
});Standalone method to detect if a PostCSS node contains any browser hacks without processing the entire stylesheet.
/**
* Detects if a PostCSS node contains any browser hacks
* @param node - PostCSS node to analyze
* @returns true if hack is detected, false otherwise
*/
function detect(node: Node): boolean;Usage:
const postcss = require('postcss');
const stylehacks = require('stylehacks');
const css = 'h1 { _color: red; color: blue; }';
const root = postcss.parse(css);
root.walkDecls(decl => {
const isHack = stylehacks.detect(decl);
if (isHack) {
console.log(`Hack detected: ${decl.toString()}`);
}
});
// Example output: "Hack detected: _color: red"Indicates PostCSS plugin compatibility.
/** PostCSS plugin compatibility flag */
const postcss: true;stylehacks relies on key dependencies for its functionality:
For the complete list of supported browser hacks, see the Detection Plugins section above.
stylehacks uses browserslist to determine which hacks should be removed based on your target browser support:
// Hacks are only removed if targeted browsers don't require them
const plugin = stylehacks({
overrideBrowserslist: [
'> 1%',
'last 2 versions',
'not dead'
]
});If your browserslist doesn't include IE6, for example, all IE6-specific hacks will be removed from your CSS.
interface Options {
/** Enable lint mode - emit warnings instead of removing hacks */
lint?: boolean;
/** Override the browserslist configuration */
overrideBrowserslist?: string | string[];
/** Path for browserslist resolution */
path?: string;
/** Environment name for browserslist */
env?: string;
/** Custom usage statistics for browserslist */
stats?: any;
}
interface Plugin {
/** PostCSS plugin name */
postcssPlugin: string;
/** Plugin preparation function */
prepare(result: Result): PluginInstance;
}
interface PluginInstance {
/** Execute after all other plugins */
OnceExit(root: Root): void;
}
/** PostCSS AST node types */
type Node = Declaration | Rule | AtRule | Comment | Root;