什么是 Stylelint #
Stylelint 是一个强大的 CSS 代码检查工具,帮助你:
- 🎯 避免错误:检测无效的 CSS 语法、拼写错误的属性名等
- 📐 强制规范:统一代码风格,如缩进、引号、命名规范等
- 🔧 自动修复:自动修复大部分格式问题
- 🔌 高度可扩展:支持 100+ 内置规则和自定义插件
- 💪 支持预处理器:SCSS、Sass、Less、SugarSS 等
- 🌐 支持现代 CSS:CSS Grid、Custom Properties、Modern Color Functions
# 安装 Stylelint
npm install --save-dev stylelint stylelint-config-standard
# 创建配置文件
echo '{"extends": ["stylelint-config-standard"]}' > .stylelintrc.json
# 运行检查
npx stylelint "**/*.css"为什么需要 Stylelint #
传统问题 #
没有代码检查工具时,CSS 代码容易出现各种问题:
/* ❌ 问题代码 */
.selector {
colro: #fff; /* 拼写错误 */
background: #FFFFFF; /* 大小写不统一 */
margin: .5px; /* 缺少前导 0 */
color: rgb(255,255,255); /* 空格不统一 */
}
.selector { /* 重复的选择器 */
color: red;
}
#id-selector {} /* 过多的 ID 选择器 */
#another-id {}结果:
- ❌ 拼写错误导致样式不生效
- ❌ 代码风格不统一,难以维护
- ❌ 潜在的性能问题
- ❌ 难以发现重复或冗余代码
使用 Stylelint 后 #
/* ✅ 规范的代码 */
.selector {
color: #fff;
background-color: #ffffff;
margin: 0.5px;
color: rgb(255, 255, 255);
}
/* Stylelint 会提示:
- 拼写错误
- 重复的选择器
- ID 选择器过多
- 格式问题(自动修复)
*/结果:
- ✅ 自动检测拼写错误
- ✅ 代码风格自动统一
- ✅ 提前发现潜在问题
- ✅ 提高代码质量
安装 #
基础安装 #
# 使用 npm
npm install --save-dev stylelint stylelint-config-standard
# 使用 yarn
yarn add -D stylelint stylelint-config-standard
# 使用 pnpm
pnpm add -D stylelint stylelint-config-standardSCSS/Sass 项目 #
npm install --save-dev stylelint stylelint-config-standard-scssVue 项目 #
npm install --save-dev stylelint stylelint-config-standard-vue完整安装(推荐) #
# Stylelint 核心 + 标准配置 + SCSS 支持 + 属性排序
npm install --save-dev \
stylelint \
stylelint-config-standard-scss \
stylelint-config-recommended-vue \
stylelint-order \
postcss postcss-html配置文件 #
支持的配置文件格式 #
Stylelint 支持多种配置文件格式:
# JavaScript(推荐)
.stylelintrc.js
.stylelintrc.cjs
.stylelintrc.mjs
stylelint.config.js
stylelint.config.cjs
stylelint.config.mjs
# JSON
.stylelintrc
.stylelintrc.json
# YAML
.stylelintrc.yaml
.stylelintrc.yml
# package.json 中配置
{
"stylelint": {
// 配置项
}
}推荐使用 .stylelintrc.js 或 stylelint.config.js。
配置文件后缀说明 #
.stylelintrc.js vs .stylelintrc.cjs vs .stylelintrc.mjs #
根据项目的模块系统选择:
1. .stylelintrc.js 或 stylelint.config.js
// .stylelintrc.js
module.exports = {
extends: ['stylelint-config-standard'],
rules: {
'color-hex-case': 'lower'
}
};使用模块系统:
package.json中"type": "commonjs"或未指定 → CommonJSpackage.json中"type": "module"→ ES Module(需要export default)
2. .stylelintrc.cjs(CommonJS 明确标识)
// .stylelintrc.cjs
module.exports = {
extends: ['stylelint-config-standard'],
rules: {
'color-hex-case': 'lower'
}
};适用场景:
- 项目是 ES Module(
"type": "module"),但配置文件需要使用 CommonJS
3. .stylelintrc.mjs(ES Module 明确标识)
// .stylelintrc.mjs
export default {
extends: ['stylelint-config-standard'],
rules: {
'color-hex-case': 'lower'
}
};适用场景:
- 项目是 CommonJS 或未指定,但配置文件想使用 ES Module
- Node.js 18+ 推荐使用
一、核心配置选项 #
1.1 extends #
作用:继承共享配置。
module.exports = {
extends: ['stylelint-config-standard']
};常用共享配置:
module.exports = {
extends: [
'stylelint-config-standard', // 标准配置(推荐)
'stylelint-config-standard-scss', // SCSS 标准配置
'stylelint-config-recommended-vue', // Vue 推荐配置
'stylelint-config-prettier' // 禁用与 Prettier 冲突的规则
]
};配置包说明:
| 配置包 | 说明 | 适用场景 |
|---|---|---|
stylelint-config-standard | CSS 标准配置,包含所有推荐规则 | 纯 CSS 项目 |
stylelint-config-standard-scss | SCSS 标准配置,扩展 CSS 配置 | SCSS/Sass 项目 |
stylelint-config-recommended-vue | Vue 推荐配置,支持 .vue 文件 | Vue 项目 |
stylelint-config-prettier | 禁用与 Prettier 冲突的规则 | 使用 Prettier 的项目 |
影响对比:
/* 不使用 extends(无规则) */
.selector {
colro: #FFF; /* ✅ 不会报错(但有拼写错误)*/
}
/* 使用 stylelint-config-standard */
.selector {
colro: #FFF; /* ❌ 错误:Unknown property "colro" */
color: #FFF; /* ⚠️ 警告:Expected "#FFF" to be "#fff" (color-hex-case) */
}1.2 plugins #
作用:加载第三方插件,扩展 Stylelint 功能。
module.exports = {
plugins: ['stylelint-order', 'stylelint-scss'],
rules: {
'order/properties-alphabetical-order': true,
'scss/at-rule-no-unknown': true
}
};常用插件:
module.exports = {
plugins: [
'stylelint-order', // 属性排序
'stylelint-scss', // SCSS 规则
'stylelint-declaration-block-no-ignored-properties', // 检测冲突属性
'stylelint-high-performance-animation' // 性能优化
]
};影响对比:
/* 不使用 stylelint-order 插件 */
.selector {
color: red;
margin: 10px;
background: blue;
padding: 5px;
}
/* ✅ 通过(但属性顺序混乱)*/
/* 使用 stylelint-order 插件 */
.selector {
color: red;
margin: 10px;
background: blue;
padding: 5px;
}
/* ❌ 错误:属性顺序不正确 */
/* 正确的顺序(可自动修复)*/
.selector {
background: blue;
color: red;
margin: 10px;
padding: 5px;
}
/* ✅ 通过 */1.3 rules #
作用:配置具体的检查规则。
module.exports = {
rules: {
'color-hex-case': 'lower',
'color-hex-length': 'short',
'indentation': 2,
'max-nesting-depth': 3
}
};规则格式:
module.exports = {
rules: {
// 格式 1:只有值
'rule-name': 'value',
// 格式 2:值 + 选项
'rule-name': ['value', { option: true }],
// 格式 3:null(禁用规则)
'rule-name': null
}
};规则严重级别:
module.exports = {
rules: {
// "error" 或 2:错误(会阻止构建)
'color-hex-case': ['error', 'lower'],
// "warning" 或 1:警告(不会阻止构建)
'color-hex-length': ['warning', 'short'],
// null:禁用规则
'indentation': null
}
};影响对比:
/* color-hex-case: 'lower' */
.selector {
color: #FFF; /* ❌ 错误:Expected "#FFF" to be "#fff" */
color: #fff; /* ✅ 通过 */
}
/* color-hex-case: 'upper' */
.selector {
color: #fff; /* ❌ 错误:Expected "#fff" to be "#FFF" */
color: #FFF; /* ✅ 通过 */
}
/* color-hex-case: null(禁用) */
.selector {
color: #FFF; /* ✅ 通过 */
color: #fff; /* ✅ 通过 */
}1.4 ignoreFiles #
作用:忽略特定文件或目录。
module.exports = {
ignoreFiles: [
'node_modules/**',
'dist/**',
'build/**',
'**/*.min.css'
]
};支持 glob 模式:
module.exports = {
ignoreFiles: [
'**/*.min.css', // 忽略所有压缩文件
'vendor/**', // 忽略 vendor 目录
'**/node_modules/**', // 忽略所有 node_modules
'src/styles/reset.css', // 忽略特定文件
'!src/styles/custom.css' // 不忽略(取消忽略)
]
};1.5 customSyntax #
作用:指定自定义语法解析器。
module.exports = {
// Vue 单文件组件
customSyntax: 'postcss-html',
// 或者针对不同文件使用不同语法
overrides: [
{
files: ['*.vue', '**/*.vue'],
customSyntax: 'postcss-html'
},
{
files: ['*.scss', '**/*.scss'],
customSyntax: 'postcss-scss'
}
]
};常用语法解析器:
| 解析器 | 说明 | 安装 |
|---|---|---|
postcss-html | 解析 HTML、Vue、Svelte 等 | npm i -D postcss-html |
postcss-scss | 解析 SCSS | npm i -D postcss-scss |
postcss-less | 解析 Less | npm i -D postcss-less |
postcss-sass | 解析 Sass | npm i -D postcss-sass |
sugarss | 解析 SugarSS | npm i -D sugarss |
1.6 overrides #
作用:针对特定文件覆盖配置。
module.exports = {
extends: ['stylelint-config-standard'],
overrides: [
// Vue 文件
{
files: ['*.vue', '**/*.vue'],
customSyntax: 'postcss-html',
rules: {
'selector-class-pattern': null // 禁用类名检查
}
},
// SCSS 文件
{
files: ['*.scss', '**/*.scss'],
customSyntax: 'postcss-scss',
extends: ['stylelint-config-standard-scss']
},
// 第三方库样式
{
files: ['vendor/**/*.css'],
rules: null // 禁用所有规则
}
]
};1.7 defaultSeverity #
作用:设置默认严重级别。
module.exports = {
defaultSeverity: 'warning', // 'error' 或 'warning'
rules: {
'color-hex-case': 'lower' // 使用默认的 warning 级别
}
};二、常用规则详解 #
2.1 颜色相关规则 #
color-hex-case #
作用:指定十六进制颜色的大小写。
module.exports = {
rules: {
'color-hex-case': 'lower' // 'lower' 或 'upper'
}
};影响对比:
/* color-hex-case: 'lower' */
.selector {
color: #FFF; /* ❌ 错误 */
color: #fff; /* ✅ 通过 */
}
/* color-hex-case: 'upper' */
.selector {
color: #fff; /* ❌ 错误 */
color: #FFF; /* ✅ 通过 */
}color-hex-length #
作用:指定十六进制颜色的长度。
module.exports = {
rules: {
'color-hex-length': 'short' // 'short' 或 'long'
}
};影响对比:
/* color-hex-length: 'short' */
.selector {
color: #ffffff; /* ❌ 错误:应该是 #fff */
color: #fff; /* ✅ 通过 */
}
/* color-hex-length: 'long' */
.selector {
color: #fff; /* ❌ 错误:应该是 #ffffff */
color: #ffffff; /* ✅ 通过 */
}color-no-invalid-hex #
作用:禁止无效的十六进制颜色。
module.exports = {
rules: {
'color-no-invalid-hex': true
}
};影响对比:
.selector {
color: #00; /* ❌ 错误:无效的十六进制颜色 */
color: #0000; /* ❌ 错误:无效的十六进制颜色 */
color: #gggggg; /* ❌ 错误:包含非十六进制字符 */
color: #000; /* ✅ 通过 */
color: #000000; /* ✅ 通过 */
}2.2 字体相关规则 #
font-family-no-duplicate-names #
作用:禁止重复的字体名称。
module.exports = {
rules: {
'font-family-no-duplicate-names': true
}
};影响对比:
.selector {
font-family: Arial, Arial, sans-serif; /* ❌ 错误:重复的 Arial */
font-family: Arial, Helvetica, sans-serif; /* ✅ 通过 */
}font-family-name-quotes #
作用:指定字体名称是否需要引号。
module.exports = {
rules: {
'font-family-name-quotes': 'always-where-required'
// 'always-where-recommended' | 'always-where-required' | 'always-unless-keyword'
}
};影响对比:
/* font-family-name-quotes: 'always-where-required' */
.selector {
font-family: Times New Roman; /* ❌ 错误:包含空格需要引号 */
font-family: "Times New Roman"; /* ✅ 通过 */
font-family: Arial; /* ✅ 通过(单词不需要引号)*/
}2.3 选择器相关规则 #
selector-class-pattern #
作用:指定类选择器的命名模式。
module.exports = {
rules: {
// BEM 命名规范
'selector-class-pattern': '^[a-z][a-z0-9]*(-[a-z0-9]+)*(__[a-z0-9]+(-[a-z0-9]+)*)?(--[a-z0-9]+(-[a-z0-9]+)*)?$',
// 或者简单的 kebab-case
'selector-class-pattern': '^[a-z][a-z0-9]*(-[a-z0-9]+)*$'
}
};影响对比:
/* BEM 命名规范 */
.block {} /* ✅ 通过 */
.block__element {} /* ✅ 通过 */
.block--modifier {} /* ✅ 通过 */
.block__element--modifier {} /* ✅ 通过 */
.Block {} /* ❌ 错误:不能以大写开头 */
.block_element {} /* ❌ 错误:应该使用双下划线 */selector-max-id #
作用:限制选择器中 ID 选择器的数量。
module.exports = {
rules: {
'selector-max-id': 0 // 不允许使用 ID 选择器
}
};影响对比:
/* selector-max-id: 0 */
#id {} /* ❌ 错误:不允许 ID 选择器 */
.class {} /* ✅ 通过 */
/* selector-max-id: 1 */
#id {} /* ✅ 通过 */
#id1 #id2 {} /* ❌ 错误:超过 1 个 ID 选择器 */selector-no-qualifying-type #
作用:禁止使用类型选择器限定其他选择器。
module.exports = {
rules: {
'selector-no-qualifying-type': true
}
};影响对比:
.selector {
div.class {} /* ❌ 错误:不应该用 div 限定 .class */
.class {} /* ✅ 通过 */
div#id {} /* ❌ 错误:不应该用 div 限定 #id */
#id {} /* ✅ 通过 */
}2.4 属性相关规则 #
property-no-unknown #
作用:禁止未知的属性。
module.exports = {
rules: {
'property-no-unknown': true
}
};影响对比:
.selector {
colro: red; /* ❌ 错误:未知的属性(拼写错误)*/
color: red; /* ✅ 通过 */
border-raidus: 5px; /* ❌ 错误:未知的属性(拼写错误)*/
border-radius: 5px; /* ✅ 通过 */
}property-case #
作用:指定属性名的大小写。
module.exports = {
rules: {
'property-case': 'lower' // 'lower' 或 'upper'
}
};影响对比:
/* property-case: 'lower' */
.selector {
COLOR: red; /* ❌ 错误:属性名应该小写 */
color: red; /* ✅ 通过 */
}2.5 数值相关规则 #
number-leading-zero #
作用:指定数字的前导零。
module.exports = {
rules: {
'number-leading-zero': 'always' // 'always' 或 'never'
}
};影响对比:
/* number-leading-zero: 'always' */
.selector {
opacity: .5; /* ❌ 错误:应该是 0.5 */
opacity: 0.5; /* ✅ 通过 */
}
/* number-leading-zero: 'never' */
.selector {
opacity: 0.5; /* ❌ 错误:应该是 .5 */
opacity: .5; /* ✅ 通过 */
}number-no-trailing-zeros #
作用:禁止数字的尾随零。
module.exports = {
rules: {
'number-no-trailing-zeros': true
}
};影响对比:
.selector {
opacity: 0.50; /* ❌ 错误:应该是 0.5 */
opacity: 0.5; /* ✅ 通过 */
margin: 1.00px; /* ❌ 错误:应该是 1px */
margin: 1px; /* ✅ 通过 */
}2.6 缩进和空格规则 #
indentation #
作用:指定缩进。
module.exports = {
rules: {
'indentation': 2, // 2 或 4 或 'tab'
// 或者带选项
'indentation': [2, {
baseIndentLevel: 1,
indentInsideParens: 'once-at-root-twice-in-block'
}]
}
};影响对比:
/* indentation: 2 */
.selector {
··property: value; /* ✅ 通过(2 个空格)*/
····property: value; /* ❌ 错误:应该是 2 个空格 */
}
/* indentation: 4 */
.selector {
····property: value; /* ✅ 通过(4 个空格)*/
··property: value; /* ❌ 错误:应该是 4 个空格 */
}string-quotes #
作用:指定字符串引号。
module.exports = {
rules: {
'string-quotes': 'single' // 'single' 或 'double'
}
};影响对比:
/* string-quotes: 'single' */
.selector {
content: "hello"; /* ❌ 错误:应该使用单引号 */
content: 'hello'; /* ✅ 通过 */
}
/* string-quotes: 'double' */
.selector {
content: 'hello'; /* ❌ 错误:应该使用双引号 */
content: "hello"; /* ✅ 通过 */
}2.7 其他重要规则 #
no-descending-specificity #
作用:禁止低优先级的选择器出现在高优先级之后。
module.exports = {
rules: {
'no-descending-specificity': true
}
};影响对比:
/* ❌ 错误:.class 比 #id .class 优先级低,但出现在后面 */
#id .class {
color: red;
}
.class {
color: blue; /* 这个规则永远不会生效 */
}
/* ✅ 通过:优先级从低到高排列 */
.class {
color: blue;
}
#id .class {
color: red;
}declaration-block-no-duplicate-properties #
作用:禁止重复的属性。
module.exports = {
rules: {
'declaration-block-no-duplicate-properties': true
}
};影响对比:
.selector {
color: red;
color: blue; /* ❌ 错误:重复的 color 属性 */
}
/* ✅ 通过 */
.selector {
color: red;
}三、完整推荐配置 #
3.1 纯 CSS 项目 #
// .stylelintrc.js
module.exports = {
extends: ['stylelint-config-standard'],
rules: {
// 颜色
'color-hex-case': 'lower',
'color-hex-length': 'short',
// 字体
'font-family-name-quotes': 'always-where-required',
// 数值
'number-leading-zero': 'always',
'number-no-trailing-zeros': true,
// 字符串
'string-quotes': 'single',
// 缩进
'indentation': 2,
// 选择器
'selector-class-pattern': '^[a-z][a-z0-9]*(-[a-z0-9]+)*$',
'selector-max-id': 0,
// 其他
'max-nesting-depth': 3,
'no-descending-specificity': null // 关闭,因为有时需要覆盖
}
};3.2 SCSS 项目 #
// .stylelintrc.js
module.exports = {
extends: [
'stylelint-config-standard-scss',
'stylelint-config-prettier' // 与 Prettier 集成
],
plugins: ['stylelint-order'],
rules: {
// CSS 规则
'color-hex-case': 'lower',
'color-hex-length': 'short',
'indentation': 2,
'string-quotes': 'single',
'selector-class-pattern': '^[a-z][a-z0-9]*(-[a-z0-9]+)*(__[a-z0-9]+(-[a-z0-9]+)*)?(--[a-z0-9]+(-[a-z0-9]+)*)?$',
// SCSS 规则
'scss/at-rule-no-unknown': true,
'scss/dollar-variable-pattern': '^[a-z][a-z0-9]*(-[a-z0-9]+)*$',
'scss/at-extend-no-missing-placeholder': true,
'scss/selector-no-redundant-nesting-selector': true,
// 属性排序
'order/properties-alphabetical-order': true
}
};3.3 Vue 3 项目 #
// .stylelintrc.js
module.exports = {
extends: [
'stylelint-config-standard-scss',
'stylelint-config-recommended-vue',
'stylelint-config-prettier'
],
plugins: ['stylelint-order'],
overrides: [
{
files: ['*.vue', '**/*.vue'],
customSyntax: 'postcss-html'
},
{
files: ['*.scss', '**/*.scss'],
customSyntax: 'postcss-scss'
}
],
rules: {
// 颜色
'color-hex-case': 'lower',
'color-hex-length': 'short',
// 字体
'font-family-name-quotes': 'always-where-required',
// 字符串
'string-quotes': 'single',
// 缩进
'indentation': 2,
// 选择器
'selector-class-pattern': null, // Vue 中组件名称可能不符合规范
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['deep', 'global'] // Vue 特殊选择器
}
],
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep'] // Vue 2 特殊选择器
}
],
// SCSS 规则
'scss/at-rule-no-unknown': true,
'scss/dollar-variable-pattern': '^[a-z][a-z0-9]*(-[a-z0-9]+)*$',
// 属性排序
'order/properties-order': [
// 定位
'position',
'top',
'right',
'bottom',
'left',
'z-index',
// 盒模型
'display',
'flex',
'flex-direction',
'flex-wrap',
'justify-content',
'align-items',
'width',
'height',
'margin',
'padding',
'border',
// 字体
'font-family',
'font-size',
'font-weight',
'line-height',
'color',
// 背景
'background',
'background-color',
'background-image',
// 其他
'opacity',
'cursor',
'transition',
'transform'
]
}
};3.4 React 项目(CSS Modules) #
// .stylelintrc.js
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-prettier'
],
plugins: ['stylelint-order'],
rules: {
// 颜色
'color-hex-case': 'lower',
'color-hex-length': 'short',
// 字符串
'string-quotes': 'single',
// 缩进
'indentation': 2,
// 选择器(CSS Modules 使用 camelCase)
'selector-class-pattern': '^[a-z][a-zA-Z0-9]+$',
// 属性排序
'order/properties-alphabetical-order': true,
// CSS Modules 特定
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'local'] // CSS Modules 伪类
}
]
}
};3.5 包含属性排序的完整配置 #
// .stylelintrc.js
module.exports = {
extends: [
'stylelint-config-standard-scss',
'stylelint-config-prettier'
],
plugins: ['stylelint-order'],
rules: {
// 基础规则
'color-hex-case': 'lower',
'color-hex-length': 'short',
'string-quotes': 'single',
'indentation': 2,
// 属性排序(按类型分组)
'order/properties-order': [
{
groupName: 'special',
emptyLineBefore: 'never',
properties: ['composes', '@import', '@extend', '@mixin']
},
{
groupName: 'positioning',
emptyLineBefore: 'never',
properties: [
'position',
'top',
'right',
'bottom',
'left',
'z-index'
]
},
{
groupName: 'boxModel',
emptyLineBefore: 'never',
properties: [
'display',
'flex',
'flex-direction',
'flex-wrap',
'justify-content',
'align-items',
'width',
'min-width',
'max-width',
'height',
'min-height',
'max-height',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'overflow',
'overflow-x',
'overflow-y'
]
},
{
groupName: 'typography',
emptyLineBefore: 'never',
properties: [
'font',
'font-family',
'font-size',
'font-weight',
'font-style',
'line-height',
'letter-spacing',
'text-align',
'text-decoration',
'text-transform',
'white-space',
'word-break',
'word-wrap',
'color'
]
},
{
groupName: 'visual',
emptyLineBefore: 'never',
properties: [
'background',
'background-color',
'background-image',
'background-repeat',
'background-position',
'background-size',
'border',
'border-radius',
'box-shadow',
'opacity'
]
},
{
groupName: 'animation',
emptyLineBefore: 'never',
properties: [
'transition',
'transition-property',
'transition-duration',
'transition-timing-function',
'animation',
'transform'
]
},
{
groupName: 'misc',
emptyLineBefore: 'never',
properties: [
'cursor',
'pointer-events',
'user-select'
]
}
]
}
};四、忽略文件 #
4.1 .stylelintignore #
创建 .stylelintignore 文件:
# 依赖
node_modules/
# 构建产物
dist/
build/
public/
# 压缩文件
**/*.min.css
# 第三方库
vendor/
lib/
# 自动生成的文件
**/*.generated.css4.2 配置文件中忽略 #
// .stylelintrc.js
module.exports = {
ignoreFiles: [
'node_modules/**',
'dist/**',
'build/**',
'**/*.min.css',
'vendor/**'
]
};4.3 在文件中忽略特定代码 #
/* stylelint-disable */
.selector {
colro: red; /* 不会报错 */
}
/* stylelint-enable */
/* 忽略下一行 */
/* stylelint-disable-next-line */
.selector { colro: red; }
/* 忽略特定规则 */
/* stylelint-disable color-hex-case */
.selector { color: #FFF; }
/* stylelint-enable color-hex-case */
/* 忽略整个文件 */
/* stylelint-disable */五、与其他工具集成 #
5.1 与 Prettier 集成 #
安装:
npm install --save-dev stylelint-config-prettier配置:
// .stylelintrc.js
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-prettier' // 必须放在最后
]
};Prettier 配置:
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"endOfLine": "lf"
}5.2 与 Git Hooks 集成(Husky + lint-staged) #
安装:
npm install --save-dev husky lint-staged
npx husky init配置:
// package.json
{
"scripts": {
"prepare": "husky",
"lint:css": "stylelint \"**/*.{css,scss,vue}\"",
"lint:css:fix": "stylelint \"**/*.{css,scss,vue}\" --fix"
},
"lint-staged": {
"*.{css,scss}": [
"stylelint --fix",
"prettier --write"
],
"*.vue": [
"stylelint --fix",
"eslint --fix",
"prettier --write"
]
}
}.husky/pre-commit:
#!/usr/bin/env sh
npx lint-staged5.3 与 VSCode 集成 #
安装扩展:
- 在 VSCode 中搜索并安装
Stylelint扩展
配置:
// .vscode/settings.json
{
// 启用 Stylelint
"stylelint.enable": true,
// 验证的文件类型
"stylelint.validate": [
"css",
"scss",
"sass",
"less",
"vue"
],
// 保存时自动修复
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": "explicit"
},
// 禁用 VSCode 内置的 CSS 验证(避免冲突)
"css.validate": false,
"scss.validate": false,
"less.validate": false
}5.4 与 CI/CD 集成 #
GitHub Actions:
# .github/workflows/lint-css.yml
name: Lint CSS
on: [push, pull_request]
jobs:
stylelint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm ci
- name: Run Stylelint
run: npm run lint:cssGitLab CI:
# .gitlab-ci.yml
lint-css:
stage: test
image: node:18
before_script:
- npm ci
script:
- npm run lint:css六、常见问题和最佳实践 #
6.1 Stylelint vs Prettier vs ESLint #
三者的区别:
Stylelint:
- CSS/SCSS 代码检查工具
- 检查 CSS 语法错误、代码质量和风格
- 可以自动修复部分问题
- 专注于样式文件
Prettier:
- 代码格式化工具
- 统一代码格式(缩进、换行、引号等)
- 支持多种语言(JS、CSS、HTML 等)
- 只关注格式,不关注代码质量
ESLint:
- JavaScript 代码检查工具
- 检查 JS 语法错误、代码质量和风格
- 可以自动修复部分问题
- 专注于 JavaScript 文件推荐配合使用:
// .stylelintrc.js(CSS 代码质量)
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-prettier' // 禁用与 Prettier 冲突的规则
]
};
// .prettierrc(代码格式)
{
"singleQuote": true,
"semi": true
}
// .eslintrc.js(JS 代码质量)
module.exports = {
extends: [
'eslint:recommended',
'plugin:prettier/recommended'
]
};6.2 配置不生效的排查 #
问题 1:找不到配置文件
# 确保配置文件在项目根目录
ls -la | grep stylelint
# 应该看到以下文件之一:
# .stylelintrc
# .stylelintrc.json
# .stylelintrc.js
# stylelint.config.js问题 2:配置文件语法错误
// ❌ 错误:拼写错误
module.exports = {
extend: ['stylelint-config-standard'] // 应该是 extends
};
// ✅ 正确
module.exports = {
extends: ['stylelint-config-standard']
};问题 3:缺少依赖
# 检查是否安装了共享配置
npm ls stylelint-config-standard
# 如果没有,安装它
npm install --save-dev stylelint-config-standard问题 4:VSCode 扩展问题
// settings.json
{
// 确保启用了 Stylelint
"stylelint.enable": true,
// 确保包含了正确的文件类型
"stylelint.validate": ["css", "scss", "vue"],
// 禁用内置的 CSS 验证
"css.validate": false
}问题 5:缓存问题
# 清除 Stylelint 缓存
npx stylelint --清除缓存
# 或者手动删除缓存目录
rm -rf node_modules/.cache/stylelint6.3 常见错误和解决方案 #
1. Unknown rule
# 错误信息
Unknown rule "color-hex-case"
# 原因:规则名称拼写错误或规则不存在
# 解决:检查规则名称是否正确2. Cannot find module 'stylelint-config-standard'
# 原因:缺少共享配置包
# 解决:安装对应的包
npm install --save-dev stylelint-config-standard3. Unexpected unknown pseudo-class selector ":deep"
// 原因:Vue 3 的 :deep 伪类选择器不被识别
// 解决:在配置中忽略
module.exports = {
rules: {
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['deep', 'global']
}
]
}
};4. Expected indentation of 2 spaces
/* 原因:缩进不正确 */
.selector {
····color: red; /* 使用了 4 个空格 */
}
/* 解决:使用 --fix 自动修复 */npx stylelint "**/*.css" --fix6.4 最佳实践 #
1. 从宽松开始,逐步严格
// 第一步:使用标准配置
module.exports = {
extends: ['stylelint-config-standard']
};
// 第二步:添加常用规则
module.exports = {
extends: ['stylelint-config-standard'],
rules: {
'color-hex-case': 'lower',
'indentation': 2
}
};
// 第三步:添加更严格的规则
module.exports = {
extends: ['stylelint-config-standard'],
rules: {
'color-hex-case': 'lower',
'indentation': 2,
'selector-max-id': 0,
'max-nesting-depth': 3
}
};2. 提交到版本控制
git add .stylelintrc.js .stylelintignore
git commit -m "chore: 添加 Stylelint 配置"3. 在 README 中说明
## 开发规范
### CSS/SCSS 代码检查
本项目使用 Stylelint 进行 CSS 代码检查。
```bash
# 检查所有样式文件
npm run lint:css
# 自动修复问题
npm run lint:css:fixVSCode 用户请安装 Stylelint 扩展,保存时自动修复。
**4. 配置 package.json 脚本**
```json
{
"scripts": {
"lint:css": "stylelint \"**/*.{css,scss,vue}\"",
"lint:css:fix": "stylelint \"**/*.{css,scss,vue}\" --fix",
"lint:css:cache": "stylelint \"**/*.{css,scss,vue}\" --cache"
}
}5. 团队协作
1. 所有成员安装 VSCode Stylelint 扩展
2. 统一使用项目的 Stylelint 配置
3. 提交前自动检查(Git hooks)
4. CI/CD 中强制检查
5. 定期 review 和更新规则七、常用命令 #
检查文件 #
# 检查单个文件
npx stylelint "src/style.css"
# 检查多个文件
npx stylelint "src/**/*.css"
# 检查多种文件类型
npx stylelint "**/*.{css,scss,vue}"自动修复 #
# 自动修复问题
npx stylelint "**/*.css" --fix
# 修复并显示修复了什么
npx stylelint "**/*.css" --fix --formatter verbose使用缓存 #
# 使用缓存(加快后续检查速度)
npx stylelint "**/*.css" --cache
# 指定缓存位置
npx stylelint "**/*.css" --cache --cache-location "node_modules/.cache/stylelint"指定配置文件 #
# 使用特定的配置文件
npx stylelint "**/*.css" --config .stylelintrc.prod.js
# 不使用配置文件
npx stylelint "**/*.css" --config-basedir false输出格式 #
# 默认格式
npx stylelint "**/*.css"
# JSON 格式
npx stylelint "**/*.css" --formatter json
# Verbose 格式(详细)
npx stylelint "**/*.css" --formatter verbose
# 输出到文件
npx stylelint "**/*.css" --output-file report.txt其他有用命令 #
# 打印有效配置
npx stylelint --print-config src/style.css
# 忽略特定模式
npx stylelint "**/*.css" --ignore-pattern "dist/**"
# 只报告错误(忽略警告)
npx stylelint "**/*.css" --quiet
# 设置最大警告数
npx stylelint "**/*.css" --max-warnings 0八、总结 #
必须配置的选项 #
module.exports = {
// 1. 继承标准配置
extends: ['stylelint-config-standard'],
// 2. 常用规则
rules: {
'color-hex-case': 'lower',
'color-hex-length': 'short',
'indentation': 2,
'string-quotes': 'single'
}
};推荐工作流 #
- 安装 Stylelint 和配置
- 配置 VSCode 扩展
- 配置 Git hooks(自动检查)
- 配置 CI/CD(强制检查)
- 团队培训和规范
学习建议 #
- 从
stylelint-config-standard开始 - 理解每个规则的作用
- 根据团队需求调整规则
- 使用
--fix自动修复 - 配合 Prettier 使用