Enforce a header comment on every stylesheet.
A stylelint custom rule that asserts every file begins with a configured header comment — typically a copyright or licence notice. When the header is missing, the rule reports an error; with --fix, it prepends the header for you.
Copyright and licence headers are easy to add and easy to forget. A pre-commit lint check is the natural place to enforce them, but stylelint doesn't ship a header rule out of the box. stylelint-header bridges the gap — point it at a string or a file and every CSS/SCSS/Less file in your project picks up the same header, formatted consistently, with --fix doing the boring work.
- Template-driven — pass a string or a path to a file; supports
lodash.templatesyntax for variables - Fuzzy matching — uses
string-similarityso cosmetic edits (whitespace, year bumps) don't trigger false positives - Auto-fixable — missing headers are prepended on
--fix, preserving the rest of the file - Minifier-friendly — opt into
/*!syntax so the header survives tools like cssnano - Built-in variables —
YEAR,FILE_NAME, andFILE_PATHare filled in automatically; bring your own as needed
yarn add --dev stylelint-header
npm install --save-dev stylelint-header
pnpm add --save-dev stylelint-header
bun add --dev stylelint-headerAdd the plugin to your stylelint config and enable the header/header rule, passing either a string template or a path to a file containing the template. To toggle the rule off, set the value to null.
{
"plugins": ["stylelint-header"],
"rules": {
"header/header": ["./COPYRIGHT"]
}
}{
"plugins": ["stylelint-header"],
"rules": {
"header/header": [
"Copyright <%= YEAR %>. <%= company %>",
{
templateVariables: {
company: "AI Overlords Inc.",
},
nonMatchingTolerance: 0.8,
},
],
},
}Type: object Default: {}
Key/value pairs used to substitute variables in the header template. Given a template like:
(c) <%= YEAR %> <%= company %>and a config of:
{
templateVariables: {
company: "AI Overlords Inc.",
},
}the resulting header becomes:
/*!
* (c) 2026 AI Overlords Inc.
*/YEAR was substituted automatically — it doesn't need to appear in templateVariables. The following variables are always available:
| Variable | Value |
|---|---|
YEAR |
The current year |
FILE_NAME |
The basename of the linted file |
FILE_PATH |
The directory of the linted file |
Templates use lodash.template — see the lodash docs for the full syntax.
Type: number between 0 and 1 Default: 0.98
Minimum similarity (per string-similarity) between the comment found at the top of the file and the configured header. Lower the value when you want to allow small drift (e.g. a stale year); raise it to enforce an exact match.
Type: boolean Default: false
When true, generated headers begin with /* rather than /*!. The /*! prefix is preserved by most CSS minifiers (e.g. cssnano) — leave the default in place if you want the header to survive minification, set to true if you don't.
- Node.js >= 24
- stylelint 16.x or 17.x
Contributions are welcome — see CONTRIBUTING.md for the full workflow, and CODE_OF_CONDUCT.md for community expectations. For bugs and ideas, please open an issue.
Apache 2.0 © Cassondra Roberts
If you find this plugin useful and would like to buy me a coffee/beer as a small thank you, I would greatly appreciate it! Funding links are available in the GitHub UI for this repo.
