Skip to content

projectwallace/stylelint-plugin

Repository files navigation

Stylelint Plugin Project Wallace Stylelint Plugin Project Wallace

@projectwallace/stylelint-plugin

A stylelint plugin that checks the complexity, design tokens, maintainability and correctness of your CSS.

  • 📏 Over 60 rules to keep your CSS in check
  • ⚙️ 5 configuration presets for different concerns
  • 🌲 Fully tree-shakeable — only pay for what you use
  • ⚡ Powered by @projectwallace/css-parser for fast parsing of selectors, values and at-rule preludes
  • 🔬 Same battle-tested analysis engine as @projectwallace/css-analyzer
  • 🚀 Zero config to get started — one extends line covers you with sensible defaults
  • 🗂️ Whole-stylesheet analysis — reasons about ratios, averages and uniqueness counts across the entire file, not just node-by-node
  • ✅ Compatible with Stylelint 16 and 17

Tip

For the most accurate results, lint your shipped CSS bundle(s) rather than source files. Rules that measure file size, uniqueness counts, and ratios mostly make sense against the CSS your users actually receive. See Holistic linting for setup examples.

Installation

npm install --save-dev @projectwallace/stylelint-plugin

Usage

Using a preset config (recommended)

The easiest way to get started is by extending one of the preset configs:

  • recommended — enables all rules with sensible defaults
  • design-tokens — enables rules that encourage the use of design tokens in your CSS
  • performance — enables rules that affect file size and loading performance
  • maintainability — enables rules that limit complexity and enforce conventions to keep CSS easy to reason about and manage over time
  • correctness - enables rules to help prevent errors
{
	"extends": ["@projectwallace/stylelint-plugin/configs/recommended"]
}

Manual configuration

Alternatively, add the plugin and configure rules individually in your stylelint config:

{
	"plugins": ["@projectwallace/stylelint-plugin"],
	"rules": {
		"projectwallace/no-static-media-queries": true,
		"projectwallace/no-unused-custom-properties": true,
		"projectwallace/no-property-shorthand": true,
		"projectwallace/no-duplicate-data-urls": true,
		"projectwallace/max-unique-colors": 128,\
		"projectwallace/max-selector-complexity": 15,
		"projectwallace/max-spacing-resets": 16,
		"projectwallace/max-important-ratio": 0.1
	}
}

Tree-shakable imports

To only load a single rule instead of the entire plugin, import it directly by rule name:

// stylelint.config.js
import maxFileSize from '@projectwallace/stylelint-plugin/rules/max-file-size'

export default {
	plugins: [maxFileSize],
	rules: {
		'projectwallace/max-file-size': 200000,
	},
}

Rules

All rules are included in the recommended config. The specialized configs below group rules by concern.

Performance

Rules that affect file size and loading performance.

Rule Description
max-comment-size Limit the total byte size of comments in a stylesheet
max-comments Prevent the total number of comments from exceeding a predefined limit.
max-embedded-content-size Limit the total byte size of embedded content (data URIs) in a stylesheet
max-file-size Limit the total byte size of a stylesheet
max-lines-of-code Prevent a stylesheet from exceeding a predefined number of lines of code
no-duplicate-data-urls Disallow the same data URL from being used more than once
no-empty-rules Disallow empty rules and at-rules (including those containing only comments)
no-unused-keyframes Disallow @keyframes that are never used in an animation-name or animation
no-unused-layers Disallow @layer names that are declared but never implemented

Design Tokens

Rules that encourage the use of design tokens in your CSS.

Rule Description
max-unique-animation-functions Limit the number of unique animation timing functions
max-unique-box-shadows Limit the number of unique box-shadow values
max-unique-color-formats Limit the number of distinct color formats
max-unique-colors Limit the number of unique color values
max-unique-durations Limit the number of unique duration values
max-unique-gradients Limit the number of unique gradient values
max-unique-font-families Limit the number of unique font families
max-unique-font-sizes Limit the number of unique font sizes
max-unique-keyframes Limit the number of unique keyframe animations
max-unique-line-heights Limit the number of unique line height values
max-unique-media-queries Limit the number of unique media queries
max-unique-supports-queries Limit the number of unique supports queries
max-unique-text-shadows Limit the number of unique text-shadow values

Correctness

Rules to help prevent errors.

Rule Description
no-unknown-container-names Disallow container names in @container that were never declared
no-unknown-custom-properties Disallow the use of undeclared custom properties in a var()
no-useless-custom-property-assignment Disallow custom property assignments that reference themselves via var()
no-unused-container-names Disallow container names that are declared but never queried
no-unused-custom-properties Disallow custom properties that are never used in a var()
no-unused-keyframes Disallow @keyframes that are never used in an animation-name or animation
no-static-container-queries Disallow static (exact-match) numeric container feature conditions
no-static-media-queries Disallow static (exact-match) numeric media feature conditions
no-unreachable-media-conditions Disallow media queries with contradictory conditions that can never match
no-empty-rules Disallow empty rules and at-rules (including those containing only comments)
no-important-in-keyframes Disallow !important declarations inside @keyframes blocks
no-invalid-z-index Disallow z-index values that are not valid 32-bit integers
no-unused-layers Disallow @layer names that are declared but never implemented

Maintainability

Rules that limit complexity and enforce conventions to keep CSS easy to reason about and manage over time.

Rule Description
max-atrules Limit the total number of at-rules in a stylesheet
max-average-declarations-per-rule Limit the average number of declarations per rule across the stylesheet
max-average-selector-complexity Limit the average selector complexity across the stylesheet
max-average-selectors-per-rule Limit the average number of selectors per rule across the stylesheet
max-average-selector-specificity Limit the average specificity across the stylesheet
max-comments Prevent the total number of comments from exceeding a predefined limit.
max-declarations Limit the total number of declarations in a stylesheet
max-declarations-per-rule Limit the number of declarations in a single rule
max-important-ratio Limit the ratio of !important declarations relative to all declarations
max-nesting-depth Limit the maximum nesting depth of CSS rules and at-rules.
max-rules Limit the total number of rules in a stylesheet
max-selector-complexity Prevent selector complexity from going over a predefined maximum
max-selector-specificity Prevent individual selector specificity from exceeding a predefined maximum
max-selectors Limit the total number of selectors in a stylesheet
max-selectors-per-rule Limit the number of selectors in a single rule
max-spacing-resets Limit the number of spacing reset declarations across the stylesheet
max-unique-color-formats Limit the number of distinct color formats used across the stylesheet
max-unique-keyframes Limit the number of unique keyframe animations defined across the stylesheet
max-unique-supports-queries Limit the number of unique supports queries used across the stylesheet
max-unique-units Limit the number of unique CSS units used across the stylesheet
max-unique-z-indexes Limit the number of unique z-index values used across the stylesheet
min-declaration-uniqueness-ratio Enforce a minimum ratio of unique declarations across the stylesheet
min-selector-uniqueness-ratio Enforce a minimum ratio of unique selectors across the stylesheet
no-anonymous-layers Disallow anonymous (unnamed) @layer blocks
no-atrule-browserhacks Disallow the use of known browser hacks in at-rule preludes
no-prefixed-atrules Disallow vendor-prefixed at-rules
no-prefixed-properties Disallow vendor-prefixed CSS properties
no-prefixed-selectors Disallow vendor-prefixed pseudo-classes and pseudo-elements in selectors
no-prefixed-values Disallow vendor-prefixed CSS values
no-property-browserhacks Prevent the use of known browserhacks for properties
no-property-shorthand Disallow the use of shorthand properties
no-value-browserhacks Disallow the use of known browser hacks in values

Holistic linting

Project Wallace highly encourages looking at your CSS with a helicopter view. Linting individual files and components is good, but we must not forget to look at the big picture. This plugin has several rules to help with that.

Rules like max-selectors, max-unique-colors, and max-file-size are most meaningful when run against your compiled CSS output (e.g. dist/styles.css), not individual source files. There are two ways to set this up.

Option 1: Separate holistic config

Create a dedicated .stylelintrc-holistic.mjs that targets your compiled output:

// .stylelintrc-holistic.mjs — using a preset (recommended)
export default {
	extends: ['@projectwallace/stylelint-plugin/configs/recommended'],
}

Or configure rules individually with the plugin:

// .stylelintrc-holistic.mjs — manual rule selection
export default {
	plugins: ['@projectwallace/stylelint-plugin'],
	rules: {
		'projectwallace/max-selectors': 4096,
		'projectwallace/max-unique-colors': 10,
		'projectwallace/max-unique-font-sizes': 4,
	},
}

Run it separately against your compiled CSS:

stylelint --config .stylelintrc-holistic.mjs "dist/**/*.css"

Option 2: Overrides in your existing config

Use stylelint's overrides to keep everything in one config file — one set of rules for source files and one for the compiled output:

// .stylelintrc.mjs
export default {
	overrides: [
		// Configure linting for source files
		{
			files: ['src/**/*.css'],
			rules: {
				// source-file rules here
			},
		},
		// Configure holistic linting
		{
			files: ['dist/**/*.css'],
			plugins: ['@projectwallace/stylelint-plugin'],
			rules: {
				'projectwallace/max-selectors': 4096,
				'projectwallace/max-unique-colors': 10,
				'projectwallace/max-font-count': 4,
			},
		},
	],
}

Make sure to include both src/ and dist/ when running stylelint:

stylelint "src/**/*.css" "dist/**/*.css"

Acknowledgements

  • Daniel Yuschick's stylelint-plugin-defensive-css has been a great learning resource while building this package and you should definitely include it in your stylelint config as well.
  • The no-static-media-queries plugin was an idea from Andy Davies.
  • Some of the rules (like no-empty-rules, no-unused-custom-properties, etc.) also exist in other plugins. Our rule are new implementations based on @projectwallace/css-parser for performance and correctness. It also helps reduce the amount of plugins needed to install.

About

A stylelint plugin pack that checks the complexity of your CSS.

Resources

License

Contributing

Stars

Watchers

Forks

Contributors