Skip to main content

Migrating to 15.0.0

This release contains significant or breaking changes.

Significant changes

Two significant changes may affect you:

  • deprecated stylistic rules
  • added the declaration-property-value-no-unknown rule

Deprecated stylistic rules

We've deprecated 76 of the rules that enforce stylistic conventions:

  • at-rule-name-case
  • at-rule-name-newline-after
  • at-rule-name-space-after
  • at-rule-semicolon-newline-after
  • at-rule-semicolon-space-before
  • block-closing-brace-empty-line-before
  • block-closing-brace-newline-after
  • block-closing-brace-newline-before
  • block-closing-brace-space-after
  • block-closing-brace-space-before
  • block-opening-brace-newline-after
  • block-opening-brace-newline-before
  • block-opening-brace-space-after
  • block-opening-brace-space-before
  • color-hex-case
  • declaration-bang-space-after
  • declaration-bang-space-before
  • declaration-block-semicolon-newline-after
  • declaration-block-semicolon-newline-before
  • declaration-block-semicolon-space-after
  • declaration-block-semicolon-space-before
  • declaration-block-trailing-semicolon
  • declaration-colon-newline-after
  • declaration-colon-space-after
  • declaration-colon-space-before
  • function-comma-newline-after
  • function-comma-newline-before
  • function-comma-space-after
  • function-comma-space-before
  • function-max-empty-lines
  • function-parentheses-newline-inside
  • function-parentheses-space-inside
  • function-whitespace-after
  • indentation
  • linebreaks
  • max-empty-lines
  • max-line-length
  • media-feature-colon-space-after
  • media-feature-colon-space-before
  • media-feature-name-case
  • media-feature-parentheses-space-inside
  • media-feature-range-operator-space-after
  • media-feature-range-operator-space-before
  • media-query-list-comma-newline-after
  • media-query-list-comma-newline-before
  • media-query-list-comma-space-after
  • media-query-list-comma-space-before
  • no-empty-first-line
  • no-eol-whitespace
  • no-extra-semicolons
  • no-missing-end-of-source-newline
  • number-leading-zero
  • number-no-trailing-zeros
  • property-case
  • selector-attribute-brackets-space-inside
  • selector-attribute-operator-space-after
  • selector-attribute-operator-space-before
  • selector-combinator-space-after
  • selector-combinator-space-before
  • selector-descendant-combinator-no-non-space
  • selector-list-comma-newline-after
  • selector-list-comma-newline-before
  • selector-list-comma-space-after
  • selector-list-comma-space-before
  • selector-max-empty-lines
  • selector-pseudo-class-case
  • selector-pseudo-class-parentheses-space-inside
  • selector-pseudo-element-case
  • string-quotes
  • unicode-bom
  • unit-case
  • value-list-comma-newline-after
  • value-list-comma-newline-before
  • value-list-comma-space-after
  • value-list-comma-space-before
  • value-list-max-empty-lines

When we created these rules, pretty printers (like Prettier) didn't exist. They now offer a better way to consistently format code, especially whitespace. Linters and pretty printers are complementary tools that work together to help you write consistent and error-free code.

By deprecating these rules, we can:

  • focus on writing and maintaining rules that help you avoid errors and enforce (non-stylistic) conventions, both of which are unique to Stylelint
  • modernize our codebase, e.g. move to ESM so that we can update our dependencies and keep Stylelint secure for you

The deprecated rules will still work in this release (with a deprecation warning). In preparation for the next major release, when we'll remove the rules from Stylelint, we suggest:

  • extending the standard config in your configuration object, if you don't already
  • removing the deprecated rules from your configuration object

You can extend the standard config using:

{
+ "extends": ["stylelint-config-standard"],
"rules": { .. }
}

Additionally, you may no longer need to extend Prettier's Stylelint config as there should be no conflicting rules:

{
- "extends": ["stylelint-config-prettier"],
"rules": { .. }
}

We've removed the deprecated rules from the latest version of the standard config. It still helps you write consistent CSS by turning on many of the other rules that enforce conventions, e.g. most of the *-notation, *-pattern and *-quotes rules.

There are lots of other rules we don't turn on in the standard config and you can learn more about using them to customize Stylelint to your exact needs in our new guide.

Alternatively, you can continue to enforce stylistic consistency with Stylelint by using the community plugin @stylistic/stylelint-plugin that has migrated the deprecated rules.

You can use the quietDeprecationWarnings option to silence the deprecation warnings.

Added declaration-property-value-no-unknown rule

We added the declaration-property-value-no-unknown rule. It will flag property-value pairs that are unknown in the CSS specifications, for example:

a {
top: red;
}

The top property accepts either a <length>, <percentage> or the auto keyword. The rule will flag red as it's a <color>.

Many of you have requested this rule, and we plan to add more like it to help you avoid errors in your CSS.

To turn it on in your configuration object:

{
"extends": ["stylelint-config-standard"],
"rules": {
+ "declaration-property-value-no-unknown": true
..
}
}

The rule uses CSSTree and its syntax dictionary of 600+ properties, 350+ types and 100+ functions. You can help identify and plug any gaps in its dictionary by either updating mdn-data or CSSTree's patch file.

If you use values that aren't in the CSS specifications, you can use the rule's secondary options to make the rule more permissive. You can either:

  • ignore properties or values outright
  • extend the properties and values syntaxes

The latter ensures only specific exceptions are allowed.

If you currently use the stylelint-csstree-validator plugin, you can continue to use it alongside the new rule by limiting the plugin to check only at-rule names and preludes.

{
"rules": {
"csstree/validator": [true, {
+ "ignoreProperties": ["/.+/"]
}]
}
}

Breaking changes

Three breaking changes may also affect you:

  • removed processors configuration property
  • removed support for Node.js 12
  • changed overrides.extends behavior

Removed processors configuration property

Processors were our first attempt to support containers of CSS, e.g. Markdown, HTML and CSS-in-JS. We later introduced custom syntaxes to fix some of the shortcomings of processors, e.g. incompatibility with the --fix option.

We've also deprecated the postcss-css-in-js custom syntax. It was not possible to maintain a monolithic custom syntax that attempted to support every CSS-in-JS library and syntax, as there are so many of them and each with variations in syntax.

You should remove the processors property from your configuration object and use a library-specific or syntax-specific (e.g. template literals) custom syntax instead.

For example, if you use styled-components:

{
- "processors": ["stylelint-processor-styled-components"],
+ "customSyntax": "postcss-styled-syntax",
"rules": { .. }
}

Other custom syntaxes include:

You'll find a complete list of them in Awesome Stylelint.

If you create a new custom syntax, please open a pull request to update Awesome Stylelint so that others can find it. For example, Stitches and vanilla-extract need syntaxes, which are object-based CSS-in-JS libraries.

Removed support for Node.js 12

Node.js 12 has reached end-of-life. We've removed support for it so that we could update some of our dependencies. You should use the following or higher versions of Node.js:

  • 14.13.1
  • 16.0.0
  • 18.0.0

Changed overrides.extends behavior

To be consistent with the overrides.plugins, we've changed the behaviour of overrides.extends to merge rather than replace.

If you would like to keep the previous behavior, you should change your config to:

{
- "extends": ["config-a"],
"overrides": [
{
"files": ["*.module.css"],
"extends": ["config-b"]
},
+ {
+ "files": ["*.css"],
+ "extends": ["config-a"]
+ }
]
}