A mighty CSS linter that helps you avoid errors and enforce conventions.
—
Complete collection of 139+ built-in rules for CSS validation and convention enforcement. Rules are categorized by CSS features and provide comprehensive coverage of modern CSS syntax, best practices, and common error patterns.
All built-in rules are accessible through the rules object with lazy loading for performance.
const rules: { readonly [name in keyof CoreRules]: Promise<CoreRules[name]> };
// Access a specific rule
const colorHexLengthRule = await rules['color-hex-length'];Rules for color values, hex notation, and color functions.
// Color hex length (short vs long)
'color-hex-length': Rule<'short' | 'long', {}, AutofixMessage>;
// Color hex alpha channel validation
'color-hex-alpha': Rule<'always' | 'never', {},
ExpectedMessage<[hex: string]> & RejectedMessage<[hex: string]>>;
// Color function notation (modern vs legacy)
'color-function-notation': Rule<'modern' | 'legacy', {
ignore: ('with-var-inside')[]
}>;
// Named color usage
'color-named': Rule<'never' | 'always-where-possible', {
ignoreProperties: (string | RegExp)[];
ignore: ('inside-function')[];
}, AutofixMessage & RejectedMessage<[keyword: string]>>;
// Invalid hex colors
'color-no-invalid-hex': Rule<true, {}, RejectedMessage<[hex: string]>>;
// Disallow hex colors entirely
'color-no-hex': Rule<true, {}, RejectedMessage<[hex: string]>>;Rules for CSS at-rules like @media, @keyframes, @import, etc.
// Unknown at-rules
'at-rule-no-unknown': Rule<true, {
ignoreAtRules: (string | RegExp)[]
}, RejectedMessage<[atRule: string]>>;
// At-rule allowlist
'at-rule-allowed-list': Rule<string[], {}, RejectedMessage<[atRule: string]>>;
// At-rule disallowlist
'at-rule-disallowed-list': Rule<string[], {}, RejectedMessage<[atRule: string]>>;
// Vendor prefixed at-rules
'at-rule-no-vendor-prefix': Rule<true, {}, RejectedMessage<[atRule: string]>>;
// Empty line before at-rules
'at-rule-empty-line-before': Rule<'always' | 'never', {
except: ('after-same-name' | 'inside-block' | 'blockless-after-same-name-blockless' | 'blockless-after-blockless' | 'first-nested')[];
ignore: ('after-comment' | 'first-nested' | 'inside-block' | 'blockless-after-same-name-blockless' | 'blockless-after-blockless')[];
ignoreAtRules: (string | RegExp)[];
}>;Rules for CSS properties and their values.
// Unknown properties
'property-no-unknown': Rule<true, {
checkPrefixed: boolean;
ignoreAtRules: (string | RegExp)[];
ignoreProperties: (string | RegExp)[];
ignoreSelectors: (string | RegExp)[];
}, RejectedMessage<[property: string]>>;
// Property allowlist
'property-allowed-list': Rule<(string | RegExp)[], {},
RejectedMessage<[property: string]>>;
// Property disallowlist
'property-disallowed-list': Rule<(string | RegExp)[], {},
RejectedMessage<[property: string]>>;
// Vendor prefixed properties
'property-no-vendor-prefix': Rule<true, {
ignoreProperties: (string | RegExp)[]
}, RejectedMessage<[property: string]>>;
// Deprecated properties
'property-no-deprecated': Rule<true, {
ignoreProperties: (string | RegExp)[];
}, AutofixMessage & RejectedMessage<[property: string]>>;Rules for CSS selectors, pseudo-classes, and combinators.
// Unknown pseudo-classes
'selector-pseudo-class-no-unknown': Rule<true, {
ignorePseudoClasses: (string | RegExp)[]
}, RejectedMessage<[selector: string]>>;
// Unknown pseudo-elements
'selector-pseudo-element-no-unknown': Rule<true, {
ignorePseudoElements: (string | RegExp)[]
}, RejectedMessage<[selector: string]>>;
// Selector specificity limits
'selector-max-specificity': Rule<string, {
ignoreSelectors: (string | RegExp)[]
}, ExpectedMessage<[selector: string, specificity: string]>>;
// Maximum nesting depth
'max-nesting-depth': Rule<number, {
ignore: ('blockless-at-rules' | 'pseudo-classes')[];
ignoreAtRules: (string | RegExp)[];
ignoreRules: (string | RegExp)[];
ignorePseudoClasses: (string | RegExp)[];
}, ExpectedMessage<[depth: number]>>;
// Class name patterns
'selector-class-pattern': Rule<string | RegExp, {
resolveNestedSelectors: boolean
}, ExpectedMessage<[input: string, pattern: string | RegExp]>>;Rules for CSS functions like calc(), url(), etc.
// Unknown functions
'function-no-unknown': Rule<true, {
ignoreFunctions: (string | RegExp)[]
}, RejectedMessage<[name: string]>>;
// Function allowlist
'function-allowed-list': Rule<(string | RegExp)[], {
exceptWithoutPropertyFallback: (string | RegExp)[]
}, RejectedMessage<[name: string]>>;
// Function disallowlist
'function-disallowed-list': Rule<(string | RegExp)[], {},
RejectedMessage<[name: string]>>;
// calc() function spacing
'function-calc-no-unspaced-operator': Rule<true, {}, {
expectedAfter: (operator: string) => string;
expectedBefore: (operator: string) => string;
}>;
// URL quotes
'function-url-quotes': Rule<'always' | 'never', {
except: ('empty')[]
}>;
// Function name case
'function-name-case': Rule<'lower' | 'upper', {
ignoreFunctions: (string | RegExp)[]
}, AutofixMessage>;Rules for CSS declarations and declaration blocks.
// Duplicate properties
'declaration-block-no-duplicate-properties': Rule<true, {
ignore: ('consecutive-duplicates' | 'consecutive-duplicates-with-different-values' | 'consecutive-duplicates-with-different-syntaxes' | 'consecutive-duplicates-with-same-prefixless-values')[];
ignoreProperties: (string | RegExp)[];
}, RejectedMessage<[property: string]>>;
// Important declarations
'declaration-no-important': Rule<true>;
// Single line declaration limits
'declaration-block-single-line-max-declarations': Rule<number, {},
ExpectedMessage<[maximum: number]>>;
// Empty line before declarations
'declaration-empty-line-before': Rule<'always' | 'never', {
except: ('first-nested' | 'after-comment' | 'after-declaration')[];
ignore: ('after-comment' | 'after-declaration' | 'first-nested' | 'inside-single-line-block')[];
}>;
// Shorthand property overrides
'declaration-block-no-shorthand-property-overrides': Rule<true, {},
RejectedMessage<[shorthand: string, property: string]>>;Rules can be configured with primary and secondary options.
type ConfigRuleSettings<T, O extends Object> =
| null // Disable rule
| undefined // Use default
| NonNullable<T> // Primary option only
| [NonNullable<T>] // Primary option in array
| [NonNullable<T>, O]; // Primary + secondary options
// Examples:
const config = {
rules: {
// Simple enable
"color-no-invalid-hex": true,
// With primary option
"color-hex-length": "short",
// With secondary options
"property-no-unknown": [true, {
ignoreProperties: ["composes"]
}],
// Disabled
"font-weight-notation": null
}
};// Pattern matching rules
type PatternRule<S extends object = {}> = Rule<string | RegExp, S,
ExpectedMessage<[input: string, pattern: string | RegExp]>>;
// Maximum value rules
type MaxRule<S extends object = {}> = Rule<number, S,
ExpectedMessage<[selector: string, maximum: number]>>;
// Notation rules (format preferences)
type NotationRule<P extends string, S extends object = {}> = Rule<P, S,
ExpectedMessage<[primary: P]>>;
// Autofix message type
type AutofixMessage = {
expected: (actual: string, expected: string) => string;
};import stylelint from "stylelint";
// Configure multiple rules
const result = await stylelint.lint({
code: css,
config: {
rules: {
// Color rules
"color-hex-length": "short",
"color-no-invalid-hex": true,
"color-named": ["always-where-possible", {
ignore: ["inside-function"]
}],
// Property rules
"property-no-unknown": [true, {
ignoreProperties: ["composes", "global"]
}],
// Selector rules
"selector-max-specificity": "0,3,0",
"selector-class-pattern": "^[a-z][a-zA-Z0-9]*$",
// At-rule configuration
"at-rule-no-unknown": [true, {
ignoreAtRules: ["extends", "include"]
}]
}
}
});Install with Tessl CLI
npx tessl i tessl/npm-stylelint