在团队协作开发项目的时候,我们会必不可少的需要写一些 css 样式表。css 虽然不算严格的编程语言,但它在前端开发体系中却占据着重要地位。css 样式表若是写的混乱没有规则,那么对于团队其他成员或后来者或维护者一定是一个令人头痛的问题,尤其是具有代码强迫症的人群。因此写出一手漂亮的,有规则的 css 样式表就显得极为重要。
我们知道在 React 项目中引入 TSLint 做代码规范 这篇文章中介绍了如何使用 TSLint 做代码规范,但 TSLint 并不能对样式表起到代码规范作用。那么在团队协作时如何才能写出统一的规范化的样式表呢?我们知道 Stylelint 是一个强大的、现代化的 CSS 检测工具,它通过定义一系列的编码风格规则帮助我们避免在样式表中出现错误.。本篇文章所要介绍的就是如何在项目中引入 Stylelint 。
注意:本篇文章以 Create React App 项目为例,至于如何创建一个 Create React App 项目请查看 React 项目中引入 TSLint 做代码规范 这篇文章中的步骤1。
步骤1:通过命令安装 stylelint、stylelint-order、stylelint-scss 安装包
a、安装 stylelint:npm install stylelint --save-dev
b、安装 stylelint-order:npm install stylelint-order --save-dev
c、安装 stylelint-scss:npm install stylelint-scss --save-dev
注意1:a 中通过命令安装的 stylelint 是使用 Stylelint 做样式表代码规范所需要的一个安装包 ----- 必须安装
注意2:b 中通过命令安装的 stylelint-order 是用来指定样式排序,比如声明的块内(插件包)属性的顺序,例如:先写定位,再写盒模型,再写内容区样式,最后写 CSS3 相关属性 ---- 推荐安装
注意3、c 中通过命令安装的 stylelint-scss 是用来执行各种各样的 SCSS 语法特性检测规则(插件包) ---- 如果是写sass样式表,必须安装,否则不用安装
注意4、除了 b 和 c 这两个插件包,你还可以 点击此处 选择其他你需要的插件包
步骤2:在项目根目录中创建 stylelint.config.js 配置文件
步骤3、根据 配置 | Configuration 中配置 stylelint.config.js 文件中的配置项
stylelint.config.js 文件中是一个大的 json 对象,其中的配置项有:
配置项 rules:规则决定检测器要查找什么和要解决什么
配置项 extends:的值是个“定位器” (或 “定位器” 数组),也是最终被 require() 的,因此,可以使用 Node 的 require.resolve() 算法适应任何格式
配置项 plugins:插件是由社区创建的规则或规则集,支持方法论、工具集,非标准 的 CSS 特性,或非常特定的用例
配置项 processors:Processors 是 stylelint 的钩子函数,可以以它的方式修改代码,也可以在它们退出时修改结果
配置项 ignoreFiles:提供一个 glob 或 globs 数组,忽略特定的文件
步骤4、根据 Rules 中的各个配置项进行配置 stylelint.config.js 文件中的配置项 rules 中的配置项
步骤5、 步骤4中根据 Rules 中配置的配置项是最基本的配置项,此外还要在配置 scss rules 和 order rules
a、因为在步骤1中安装了 stylelint-scss 插件,所以要根据 List of rules 配置相应的 scss rules
b、因为在步骤1中安装了 stylelint-order 插件,所以要根据 stylelint-order 中的 Rules 配置相应的 order rules
步骤6:以 vscode 编辑器为例,需要在 vscode 中安装 stylelint 插件
步骤7、重启编辑器修改样式文件中的声明的块内属性的顺序,查看是否会出现错误警告
备注:我的项目中的 stylelint.config.js 文件 中的配置如下(没有截图,方便拷贝)
module.exports = {
plugins: [
'stylelint-scss',
'stylelint-order'
],
rules: {
// Possible errors
'color-no-invalid-hex': true,
'font-family-no-missing-generic-family-keyword': true,
'function-calc-no-unspaced-operator': true,
'function-linear-gradient-no-nonstandard-direction': true,
'unit-no-unknown': true,
'property-no-unknown': true,
'declaration-block-no-duplicate-properties': true,
'declaration-block-no-shorthand-property-overrides': true,
'selector-pseudo-class-no-unknown': true,
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['ng-deep']
}
],
'media-feature-name-no-unknown': true,
'comment-no-empty': true,
'no-duplicate-at-import-rules': true,
'no-duplicate-selectors': true,
'no-empty-source': true,
'no-extra-semicolons': true,
'no-invalid-double-slash-comments': true,
// Limit language features
'unit-blacklist': [],
'shorthand-property-no-redundant-values': true,
'value-no-vendor-prefix': true,
'property-blacklist': [''],
'property-no-vendor-prefix': true,
'declaration-block-no-redundant-longhand-properties': true,
'declaration-no-important': true,
'declaration-property-unit-blacklist': {},
'declaration-property-unit-whitelist': {
'font-size': ['px', 'rem', 'vmin']
},
'declaration-property-value-whitelist': {
'float': ['none']
},
'selector-max-compound-selectors': 4,
'selector-max-empty-lines': 0,
'selector-max-id': 1,
'selector-no-vendor-prefix': true,
'media-feature-name-no-vendor-prefix': true,
'at-rule-no-vendor-prefix': true,
'at-rule-blacklist': ['extend'],
// Stylistic issues
'color-hex-case': 'lower',
'color-hex-length': 'short',
'font-family-name-quotes': 'always-where-recommended',
'function-comma-space-after': 'always',
'function-comma-space-before': 'never',
'function-name-case': 'lower',
'function-parentheses-space-inside': 'never',
'function-url-quotes': 'never',
'function-whitespace-after': 'always',
'font-weight-notation': 'numeric',
'number-leading-zero': 'always',
'number-no-trailing-zeros': true,
'string-quotes': [
'double',
{
'avoidEscape': true
}
],
'length-zero-no-unit': true,
'unit-case': 'lower',
'value-keyword-case': [
'lower',
{
ignoreProperties: ['family']
}
],
'value-list-comma-newline-after': 'always-multi-line',
'value-list-comma-space-after': 'always-single-line',
'value-list-comma-space-before': 'never',
'value-list-max-empty-lines': 0,
'property-case': 'lower',
'declaration-bang-space-after': 'never',
'declaration-bang-space-before': 'always',
'declaration-colon-space-after': 'always-single-line',
'declaration-colon-space-before': 'never',
'declaration-empty-line-before': 'never',
'declaration-block-single-line-max-declarations': 1,
'declaration-property-value-blacklist': {
'/^border/': ['none']
},
'block-closing-brace-empty-line-before': 'never',
'block-closing-brace-newline-before': 'always',
'block-opening-brace-newline-after': 'always',
'block-opening-brace-space-before': 'always',
'selector-attribute-brackets-space-inside': 'never',
'selector-attribute-operator-space-after': 'never',
'selector-attribute-operator-space-before': 'never',
'selector-attribute-quotes': 'always',
'selector-combinator-space-after': 'always',
'selector-combinator-space-before': 'always',
'selector-descendant-combinator-no-non-space': true,
'selector-pseudo-class-case': 'lower',
'selector-pseudo-class-parentheses-space-inside': 'never',
'selector-pseudo-element-case': 'lower',
'selector-pseudo-element-colon-notation': 'single',
'selector-type-case': 'lower',
'selector-list-comma-newline-after': 'always-multi-line',
'selector-list-comma-space-after': 'always-single-line',
'selector-list-comma-space-before': 'never',
'rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'first-nested']
}
],
'media-feature-colon-space-after': 'always',
'media-feature-colon-space-before': 'never',
'media-feature-name-case': 'lower',
'media-feature-parentheses-space-inside': 'never',
'media-feature-range-operator-space-after': 'always',
'media-feature-range-operator-space-before': 'always',
'at-rule-empty-line-before': [
'always',
{
ignore: ['after-comment', 'blockless-after-same-name-blockless'],
except: ['first-nested'],
ignoreAtRules: ['else']
}
],
'at-rule-name-space-after': 'always',
'at-rule-semicolon-space-before': 'never',
'comment-empty-line-before': [
'always',
{
except: ['first-nested']
}
],
'comment-whitespace-inside': 'always',
indentation: 2,
'max-empty-lines': [
1,
{
ignore: ['comments']
}
],
'no-eol-whitespace': [
true,
{
ignore: ['empty-lines']
}
],
// Sass rules
'scss/at-else-closing-brace-newline-after': 'always-last-in-chain',
'scss/at-else-closing-brace-space-after': 'always-intermediate',
'scss/at-else-empty-line-before': 'never',
'scss/at-else-if-parentheses-space-before': 'always',
'scss/at-function-named-arguments': 'never',
'scss/at-function-parentheses-space-before': 'always',
'scss/at-if-closing-brace-newline-after': 'always-last-in-chain',
'scss/at-if-closing-brace-space-after': 'always-intermediate',
'scss/at-mixin-argumentless-call-parentheses': 'always',
'scss/at-mixin-named-arguments': 'never',
'scss/at-mixin-parentheses-space-before': 'always',
'scss/at-rule-no-unknown': true,
'scss/dollar-variable-colon-newline-after': 'always-multi-line',
'scss/dollar-variable-colon-space-after': 'always-single-line',
'scss/dollar-variable-colon-space-before': 'never',
'scss/dollar-variable-empty-line-before': [
'always',
{
except: ['after-comment', 'after-dollar-variable', 'first-nested']
}
],
'scss/dollar-variable-no-missing-interpolation': true,
'scss/dollar-variable-pattern': '^_?[a-z]+[\\w-]*$',
'scss/at-extend-no-missing-placeholder': true,
'scss/at-import-no-partial-leading-underscore': true,
'scss/double-slash-comment-empty-line-before': 'always',
'scss/double-slash-comment-whitespace-inside': 'always',
'scss/declaration-nested-properties': 'never',
'scss/operator-no-newline-after': true,
'scss/operator-no-newline-before': true,
// 'scss/operator-no-unspaced': true, // Causing url parsing error, temporarily disabled.
'scss/selector-no-redundant-nesting-selector': true,
'scss/no-duplicate-dollar-variables': true,
// Order rules
'order/order': [
'custom-properties',
'dollar-variables',
'declarations',
{
type: 'at-rule',
hasBlock: false
},
'rules',
{
type: 'at-rule',
hasBlock: true
}
],
'order/properties-order': [
[
'content',
'position', 'top', 'right', 'bottom', 'left',
'display', 'flex-flow', 'flex-direction', 'flex-wrap', 'justify-content', 'align-content', 'align-items',
'flex', 'flex-grow', 'flex-shrink', 'flex-basis', 'align-self', 'order',
'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
'outline', 'outline-width', 'outline-style', 'outline-color', 'outline-offset',
'box-shadow', 'box-sizing',
'border-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius', 'border-top-left-radius',
'border', 'border-width', 'border-style', 'border-color',
'border-top', 'border-top-width', 'border-top-style', 'border-top-color',
'border-right', 'border-right-width', 'border-right-style', 'border-right-color',
'border-bottom', 'border-bottom-width', 'border-bottom-style', 'border-bottom-color',
'border-left', 'border-left-width', 'border-left-style', 'border-left-color',
'border-image', 'border-image-source', 'border-image-slice', 'border-image-width', 'border-image-outset', 'border-image-repeat',
'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',
'max-width', 'max-height', 'min-width', 'min-height', 'width', 'height',
'background', 'background-attachment', 'background-clip', 'background-origin', 'background-size', 'background-color', 'background-image', 'background-position', 'background-repeat',
'table-layout', 'border-collapse', 'border-spacing', 'caption-side', 'empty-cells',
'font', 'font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family'
],
{
unspecified: 'bottom'
}
]
}
};
参考网址:
stylelint 英文:https://stylelint.io/
stylelint 中文:https://cloud.tencent.com/developer/chapter/18030
stylelint-order: https://github.com/hudochenkov/stylelint-order
stylelint-scss:https://github.com/kristerkari/stylelint-scss
https://www.cnblogs.com/jiaoshou/p/11284204.html
https://www.cnblogs.com/xiaohuochai/p/9078154.html