Stylelint

An extensible CSS linter that catches errors and enforces consistent styling conventions.

Tool
npm
v17.16.0
11,538 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
91 /100 Excellent
Development Activity 100
Maintenance 96
Community 68
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
91 /100 Excellent
Architecture 88
Code Quality 92
Innovation 84
Learning Curve 100

Stylelint is a mighty CSS linter used to catch syntax errors, flag problematic-but-valid patterns like duplicate selectors, and enforce team conventions such as notation styles, naming patterns, and selector limits. It ships with over 100 built-in rules covering modern CSS syntax and features, and can automatically fix many of the problems it finds.

Beyond plain CSS, Stylelint understands CSS-like languages including Sass, Less, and SugarSS through custom syntax support, and can extract and lint embedded styles from HTML, Markdown, and CSS-in-JS template literals. A plugin system lets teams write their own rules, and shareable configs let organizations package and distribute their conventions across projects. It is commonly paired with a formatter like Prettier, with Stylelint handling correctness and convention enforcement while the formatter handles whitespace and layout.

What You Get

  • 100+ built-in rules covering modern CSS syntax, at-rules, custom properties, and color/value notations
  • Automatic fixing (--fix) for a large subset of rules, reducing manual cleanup after a lint run
  • Shareable, extensible configs (extends) so an organization can define conventions once and reuse them across repos
  • A plugin API for writing custom rules and custom syntaxes beyond the built-in rule set
  • Support for linting CSS embedded in HTML, Markdown, and CSS-in-JS template literals, plus Sass/Less/SugarSS via custom syntaxes
  • Multiple output formatters (JSON, compact, TAP, Unix, verbose) for wiring into CI, editors, or other tooling

Common Use Cases

  • Enforcing a shared CSS style guide across a team or organization via a shareable config
  • Catching CSS errors (invalid values, unknown properties, malformed grid areas) before they ship
  • Auto-fixing formatting-adjacent CSS issues as part of a pre-commit hook or CI pipeline
  • Linting CSS-in-JS or CSS embedded in Markdown/HTML documentation alongside the rest of a codebase

Under The Hood

Architecture

Standalone.mjs is the orchestrating core: it resolves configuration for each target through getConfigForFile.mjs and augmentConfig.mjs (cosmiconfig-based discovery with cascading extends/plugins merging), discovers files via fast-glob/globby with ignore-file support, parses each one into a PostCSS AST through getPostcssResult.mjs (with pluggable custom syntaxes for SCSS/Less/CSS-in-JS), and applies the enabled rules by walking that AST in lintPostcssResult.mjs, collecting warnings through a shared report() utility. createStylelint.mjs assembles an internal API object shared across a run, and results are shaped into LintResult objects rendered by interchangeable formatters. The CLI is a thin wrapper around the same standalone() entry point used by the Node.js API and the PostCSS-plugin integration, so all three surfaces share one execution path.

Tech Stack

Node.js 20.19+, authored as ESM throughout. PostCSS is the parsing engine, complemented by postcss-value-parser, postcss-selector-parser, and postcss-safe-parser plus the @csstools/* family for tokenizing, media queries, and selector specificity. Config discovery runs on cosmiconfig; file matching on fast-glob, globby, and micromatch; CLI argument parsing on meow; caching on file-entry-cache; and fixes are written safely via write-file-atomic. Type declarations are hand-authored rather than compiled from source, checked against usage via tsc in CI.

Code Quality

Testing is extensive: Jest drives per-rule test suites (each of the 150+ rules has its own tests directory with fixtures), coverage thresholds are enforced at 90% branches/functions/lines, and Node’s built-in test runner covers CJS/ESM interop system tests separately. ESLint’s flat config runs with —max-warnings=0 alongside Prettier, wired through lint-staged and a git pre-commit hook, and CI runs lint, type-check, and both test suites on every change. Rule modules follow a consistent functional shape (options validated via validateOptions.mjs, messages templated via ruleMessages.mjs, warnings emitted via report()) with JSDoc type annotations standing in for full TypeScript source.

API Design Three equally-supported entry points — CLI, Node.js API, and PostCSS plugin — let Stylelint slot into build tools, editors, or ad hoc scripts without redesigning the calling code. Its config model (extends/plugins/rules, cascading per-directory resolution) closely mirrors ESLint’s, so JavaScript-ecosystem developers already familiar with that shape get near-zero ramp-up. Writing a custom rule is minimal boilerplate — a function of an option that returns an AST-walking function — and each built-in rule ships its own README with runnable examples, a documentation depth few linters match at this scale.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers