"A mighty CSS linter that helps you avoid errors and enforce conventions."
Homepage: https://stylelint.io/
-
Install via
npm init stylelint
-
Install manually:
npm install --save-dev stylelint stylelint-config-standard
- SCSS syntax - a custom syntax to parse SCSS
- SCSS plugin - a set of custom rules for SCSS
npx stylelint "**/*.css"
- Update
package.json
"scripts": {
"lint:css": "stylelint **/*.css",
"lint:css:fix": "stylelint **/*.css --fix"
...
},
- Run command
npm run lint:css
Stylelint accepts a wide range of configuration file types. It will search for the following files, in this order, and move up the directory tree until found.
stylelint
property in "package.json".stylelintrc
.stylelintrc.{cjs,mjs,js,json,yaml,yml}
stylelint.config.{cjs,mjs,js}
Rules fall into 2 main categories:
Rules exist on 3 levels:
Disabled
: The rule does not apply.
rules: {
'selector-class-pattern': null
}
Warning
: Drop the severity and do not throw an error.
rules: {
'property-no-vendor-prefix': [
true,
{
'severity': 'warning'
}
]
}
Error
: Throws an error.
rules: {
'unit-allowed-list': ['em', 'rem', 's']
}
rules: {
'custom-property-pattern': [
'^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',
{
message: 'Expected custom property name to be kebab-case'
}
]
}
Stylelint also rule sets which can be extending:
extends: [
'stylelint-config-standard'
],
Use one of the following techniques to ignore code:
- Blocks of code.
/* stylelint-disable */
a {}
/* stylelint-enable */
- Specific rules blocks of code.
/* stylelint-disable selector-max-id, declaration-no-important */
#id {
color: pink !important;
}
/* stylelint-enable selector-max-id, declaration-no-important */
- Individual lines.
#id { /* stylelint-disable-line */
color: pink !important; /* stylelint-disable-line declaration-no-important */
}
#id {
/* stylelint-disable-next-line declaration-no-important */
color: pink !important;
}
- Add to glob patterns to
.stylelingignore
.
vendor/**/*.css
https://stylelint.io/awesome-stylelint/
"stylelint.enable": true,
"stylelint.configBasedir": "${workspaceFolder}",
"stylelint.reportNeedlessDisables": true,
"stylelint.reportInvalidScopeDisables": true,
"[css]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "stylelint.vscode-stylelint"
},
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": "explicit"
}
Adds checks and fixed related to accessibility.
rules: {
'a11y/content-property-no-static-value': true,
'a11y/font-size-is-readable': true,
'a11y/line-height-is-vertical-rhythmed': true,
// 'a11y/media-prefers-reduced-motion': true,
// 'a11y/media-prefers-color-scheme': true,
'a11y/no-outline-none': true,
'a11y/no-display-none': true,
'a11y/no-obsolete-attribute': true,
'a11y/no-obsolete-element': true,
'a11y/no-spread-text': true,
'a11y/no-outline-none': true,
'a11y/no-text-align-justify': true,
'a11y/selector-pseudo-class-focus': true,
}
Convert all colors into the same format.
rules: {
'color-format/format': {
format: 'hsl'
}
}
Disallow close that are close to being identical.
rules: {
"plugin/stylelint-no-indistinguishable-colors": [
true, {
ignore: [],
threshold: 3,
allowEquivalentNotation: true,
},
],
}
Checks CSS against target browsers and disallows CSS feature not supported.
rules: {
'plugin/no-unsupported-browser-features': [true, {
browsers: ['> 1%', 'Last 2 versions'],
ignore: ['rem'],
ignorePartialSupport: true
}]
}
rules: [
'order/order': [
'custom-properties',
'dollar-variables',
{
type: 'at-rule',
name: 'include'
},
'declarations',
{
type: 'at-rule',
hasBlock: true,
},
'rules'
],
// 'order/properties-alphabetical-order': true,
'order/properties-order': [
[
'content',
// Position
'position', 'z-index', 'top', 'right', 'bottom', 'left',
// Display
'display',
'flex', 'flex-direction', 'flex-grow', 'flex-shrink', 'flex-basis', 'flex-flow', 'flex-wrap',
'align', 'align-content', 'align-items', 'align-self',
'justify', 'justify-content', 'justify-items', 'justify-self',
'grid', 'grid-auto-columns', 'grid-auto-rows', 'grid-template-areas', 'grid-area',
'overflow', 'overflow-x', 'overflow-y',
'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 'border-width', 'border-style', 'border-color', 'border-radius',
'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
'width', 'min-width', 'max-width',
'height', 'min-height', 'max-height', 'opacity',
'box', 'box-sizing',
// Background
'background', 'background-color', 'background-image', 'background-repeat', 'background-attachment',
'background-position', 'background-size',
// Text
'font', 'font-family', 'font-size', 'font-weight',
'color', 'text', 'line-height', 'list-style',
// Animation
'animation',
], {
unspecified: 'bottomAlphabetical'
}
],
]