Powerful ESLint rules for CSS
The rules work with the @eslint/css language plugin.
eslint-plugin-unicorn has more rules that also lint CSS, such as no-zero-fractions and no-shorthand-property-overrides.
We do not accept pull requests because of too much AI slop.
npm install --save-dev eslint @eslint/css eslint-cssicorn
Requires ESLint >=10.4, flat config, and ESM.
Use a preset config or configure each rule in eslint.config.js.
If you don't use a preset, set language: 'css/css' and add the @eslint/css plugin, as shown below.
import css from '@eslint/css';
import cssicorn from 'eslint-cssicorn';
import {defineConfig} from 'eslint/config';
export default defineConfig([
{
files: [
'**/*.css',
],
plugins: {
css,
cssicorn,
},
language: 'css/css',
rules: {
'cssicorn/prefer-short-hex-color': 'error',
'cssicorn/…': 'error',
},
},
// …
]);
To lint fenced CSS blocks in Markdown, configure the @eslint/markdown processor. The presets match its extracted .css files. Lint Markdown prose separately.
import markdown from '@eslint/markdown';
import cssicorn from 'eslint-cssicorn';
export default [
{
files: [
'**/*.md',
],
plugins: {
markdown,
},
language: 'markdown/commonmark',
processor: 'markdown/markdown',
},
cssicorn.configs.recommended,
];
💼 Configurations enabled in.
✅ Set in the recommended configuration.
☑️ Set in the unopinionated configuration.
🔧 Automatically fixable by the --fix CLI option.
💡 Manually fixable by editor suggestions.
| Name | Description | 💼 | 🔧 | 💡 |
|---|---|---|---|---|
| consistent-compound-selector-order | Enforce consistent ordering of compound selector components. | ✅ | 🔧 | |
| consistent-layer-order | Enforce consistent ordering of cascade layer statements. | ✅ | 🔧 | |
| consistent-property-order | Enforce consistent ordering of CSS properties. | 🔧 | 💡 | |
| consistent-value-order | Enforce consistent ordering of CSS value components. | ✅ | 🔧 | |
| lowercase | Enforce lowercase CSS syntax. | ✅ | 🔧 | |
| no-clamped-values | Disallow CSS values that browsers silently clamp. | ✅ | ||
| no-declarations-after-nested-rules | Disallow declarations after nested rules. | ✅ ☑️ | ||
| no-deprecated-features | Disallow deprecated CSS features. | ✅ | 🔧 | 💡 |
| no-descending-specificity | Disallow lower-specificity selectors from following higher-specificity selectors that set the same property. | |||
| no-disabled-pinch-zoom | Disallow touch-action values that disable browser pinch zoom. |
✅ | 💡 | |
| no-duplicate-at-rule-definitions | Disallow duplicate named at-rule definitions. | ✅ | ||
| no-duplicate-font-family-names | Disallow duplicate font family names. | ✅ ☑️ | 🔧 | |
| no-duplicate-properties | Disallow duplicate properties within CSS declaration blocks. | ✅ | 💡 | |
| no-duplicate-selectors | Disallow duplicate CSS selectors. | ✅ | 🔧 | |
| no-ineffective-keyframe-declarations | Disallow ineffective declarations in keyframes. | ✅ ☑️ | 🔧 | |
| no-ineffective-overrides | Disallow state and conditional overrides blocked by cascade priority. | ✅ | ||
| no-ineffective-properties | Disallow properties that have no effect given other declarations or shorthand defaults. | ✅ ☑️ | ||
| no-ineffective-selector-properties | Disallow properties that cannot affect their selected targets. | ✅ ☑️ | 🔧 | |
| no-ineffective-supports-conditions | Disallow supports conditions that do not test their value functions. | ✅ | ||
| no-ineffective-transitions | Disallow transition targets that cannot transition under the declared behavior. | ✅ ☑️ | 💡 | |
| no-invalid-media-features | Disallow unknown media features, invalid values, and invalid notation. | ✅ ☑️ | ||
| no-invalid-property-references | Disallow invalid property references in transitions and will-change. | ✅ ☑️ | ||
| no-layout-animations | Disallow animating properties that can affect layout. | |||
| no-nesting-with-mixed-specificity | Disallow mixed specificity in nesting parents and selector-list pseudo-classes. | ✅ | ||
| no-overflow-axis-coercion | Disallow overflow values that are coerced by the other axis. | ✅ ☑️ | ||
| no-redundant-functions | Disallow redundant function calls and arguments. | ✅ | 🔧 | |
| no-redundant-longhand-properties | Disallow longhand properties that can be combined into a shorthand. | ✅ | 🔧 | |
| no-redundant-nested-style-rules | Disallow nested style rules that do not modify the parent selector. | ✅ | 🔧 | |
| no-redundant-nesting-selector | Disallow redundant nesting selectors. | ✅ | 🔧 | |
| no-redundant-shorthand-values | Disallow redundant values in CSS shorthand properties. | ✅ | 🔧 | |
| no-self-referencing-custom-properties | Disallow cyclic dependencies in CSS custom properties. | ✅ ☑️ | ||
| no-unknown-animations | Disallow unknown animations. | |||
| no-unknown-annotations | Disallow unknown and noncanonical CSS annotations. | ✅ ☑️ | 🔧 | 💡 |
| no-unknown-pseudo-selectors | Disallow unknown pseudo-class and pseudo-element selectors. | ✅ ☑️ | ||
| no-unknown-type-selectors | Disallow unknown type selectors. | ✅ ☑️ | ||
| no-unscoped-nesting-selector | Disallow unscoped CSS nesting selectors. | ✅ ☑️ | ||
| no-useless-is | Disallow unnecessary :is() wrappers. |
✅ ☑️ | 🔧 | |
| no-zero-length-unit | Disallow units on zero CSS lengths. | ✅ | 🔧 | |
| prefer-aspect-ratio | Prefer aspect-ratio over zero-height percentage-padding workarounds. |
✅ | ||
| prefer-clamp | Prefer clamp() over nested min() and max(). |
✅ ☑️ | 🔧 | |
| prefer-current-color | Prefer currentcolor over repeating the foreground color. | ✅ | 💡 | |
| prefer-existing-custom-properties | Prefer existing custom properties over matching literal values. | ✅ | 💡 | |
| prefer-explicit-viewport-units | Prefer explicit viewport units. | ✅ | 💡 | |
| prefer-individual-transform-properties | Prefer individual transform properties over transform functions. | ✅ | 💡 | |
| prefer-light-dark | Prefer light-dark() over paired light and dark color declarations. |
✅ | 💡 | |
| prefer-media-feature-range-syntax | Prefer modern media feature range syntax. | ✅ | 🔧 | 💡 |
| prefer-merged-rules | Prefer merging adjacent rules with identical declarations or conditions. | ✅ | 🔧 | |
| prefer-modern-syntax | Prefer modern CSS color and pseudo-element syntax. | ✅ | 🔧 | |
| prefer-nesting | Prefer CSS nesting for structural :is() groups and rules extending an existing parent. |
✅ | 🔧 | |
| prefer-relative-colors | Prefer relative colors for alpha variants of existing color custom properties. | ✅ | 💡 | |
| prefer-short-hex-color | Prefer short hexadecimal color notation. | ✅ | 🔧 | |
| require-prefers-reduced-motion | Require motion effects inside prefers-reduced-motion: no-preference media queries. |
|||
| require-property-descriptors | Require descriptors in CSS @property rules. |
✅ ☑️ | ||
| require-selector-scope | Require a positive scoping boundary for every selector. |
See the ESLint docs for more information about extending config files.
Note: The preset configs apply to **/*.css files. They also set language: 'css/css' and add the @eslint/css plugin.
This plugin exports a recommended config that enforces good practices.
import cssicorn from 'eslint-cssicorn';
import {defineConfig} from 'eslint/config';
export default defineConfig([
// …
cssicorn.configs.recommended,
{
files: [
'**/*.css',
],
rules: {
'cssicorn/no-unknown-animations': 'error',
},
},
]);
This plugin exports an unopinionated config with bug checks and straightforward simplifications.
import cssicorn from 'eslint-cssicorn';
import {defineConfig} from 'eslint/config';
export default defineConfig([
// …
cssicorn.configs.unopinionated,
]);
This plugin exports an all config that enables every rule.
import cssicorn from 'eslint-cssicorn';
import {defineConfig} from 'eslint/config';
export default defineConfig([
// …
cssicorn.configs.all,
{
files: [
'**/*.css',
],
rules: {
'cssicorn/prefer-short-hex-color': 'off',
},
},
]);
package.json.