CSS


2018-11-11 CSS

BEM

BEM 命名原则

BEM 为块(block)、元素(element)、修饰符(modifier)的简写,亦即命名由这三者构成。简单理解可参阅 【译】BEM CSS命名规范一 Quick start命名以下面三种连接方式组成

- 中划线 :仅作为连字符使用,表示某个块或者某个子元素的多单词之间的连接记号
__ 双下划线:双下划线用来连接块和块的子元素
_ 单下划线:单下划线用来描述一个块或者块的子元素的一种状态

下图普通网站为例,以布局的维度去检视话,我们可以得出 Header、main-content、footer 等块, BEM.png 若区块再加入功能维度,以 Header 来说,便会有 Logo,Search,Auth、Menu 块,这应该也是我们可以理解的视角。
抓出 Search 来看(块 block),有 input 与 button 等 item(元素 element)组成,于是 DOM 结构的命名就会如下

<div class="header">
    <div class="header-search">
        <div class="header-search__input">我是输入栏位</div>
        <div class="header-search__button">我是送出按钮</div>
    </div>
</div>
1
2
3
4
5
6

一个独立的块可以放置在页面的任意位置 ,不依赖。
块里也有可能再嵌套块,.header (块 block)里会有 .header-seach(块 block)
.header-search 的 "-",表示是 header 里的 search 区块。用于命名的强化说明,成为可识别的关键字。
.header-search__input 的 "__"(双底线),表示 .header-search (块 block)下面的 input(元素 element)

<ul class="header-menu">
    <li class="header-menu__item"></li>
    <li class="header-menu__item"></li>
    <li class="header-menu__item_selected"></li>
    <li class="header-menu__item"></li>
</ul>
1
2
3
4
5
6

.header-menu 的 "-",表示是 header 里的 menu 区块。用于命名的强化说明。 .header-menu__item 的 "__"(双底线),表示 .header-menu (块 block)下面的 item(元素 element) .header-menu__item_selected 的 "_"(单底线),表示当前选择的状态,属修饰。

以上两个例子就可以很清楚明白块(block)、元素(element)、修饰符(modifier)的命名

<!--以模块为单位命名-->
<div class="travel-article">
    <div class="travel-article__body">
        <div class="tag"></div>
        <button class="travel-article__button_primary"></button>
        <button class="travel-article__button_success"></button>
    </div>
</div>
1
2
3
4
5
6
7
8

以上可以看出 travel-article 是块(block),下面有 body(__body) 跟 button (__button)两个元素,且 button 有 primary(_primary) 与 success (_success)两种状态。 .tag 是通用,亦即区块内也可以放进各区块通用的样式

修饰符(modifier)亦可用来区别同性质块在不同布局的使用

<ul class="menu-header">
    <li class="menu-header__item"></li>
    <li class="menu-header__item"></li>
    <li class="menu-header__item_selected"></li>
    <li class="menu-header__item"></li>
</ul>
 
......中间省略
 
<ul class="menu-footer">
    <li class="menu-footer__item"></li>
    <li class="menu-footer__item"></li>
    <li class="menu-footer__item_selected"></li>
    <li class="menu-footer__item"></li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

总结:

基本使用规则:

- 中划线 :仅作为连字符使用,表示某个块或者某个子元素的多单词之间的连接记号;
__ 双下划线:双下划线用来连接块和块的子元素;
_ 单下划线:单下划线用来描述一个块或者块的子元素的一种状态;

使用事项:
  • 类名
    类名最好使用代码块的功能性命名,方便查找和修改;

  • 复用组件
    在使用 BEM 时;对于复用性的组件需要注意组件本身和其上下文的粘合度;要确保组件被复用时,CSS 能正常使用。

  • 什么时候使用
    使用 BEM 的诀窍是,你要知道什么时候哪些东西是应该写成 BEM 格式的。并不是每个地方都应该使用 BEM 命名方式。比如只是一条公共的单独的样式,就没有使用 BEM 格式的意义。当需要明确关联性的模块关系时,应当使用 BEM 格式。

  • 避免命名方式过长的槽点
    一般来说会使用通过 LESS/SASS 等预处理器语言来编写 CSS,利用 LESS/SASS 特性书写嵌套的过度引起的类名过长;

以 LESS 为例:

.article-tech {
    max-width: 1200px;
 
    &__body {
        padding: 20px;
    }
 
    &__button {
        padding: 5px 8px;
 
        &_primary {background: blue;}
        &_success {background: green;}
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

BEM 最难的部分之一是明确作用域是从哪开始和到哪结束的,以及什么时候使用或不使用它。如果一味的套用;就会出现特别长的类名;随着不断使用的经验积累,你慢慢就会知道怎么用,这些问题也不再是问题。技术无好坏,合适方最好。

其他命名原则

JavaScript 的驼峰式命名法(camel case)是一种惯例。但并不适用于 CSS。 CSS 以 - (连字符)进行分隔。

// bed
.redBox {
   font-weight: 10em
}

// nice ,同时,这也和 CSS 属性名称保持了一致。
.red-box {
   font-weight: 10em
}
1
2
3
4
5
6
7
8
9

使用 js- 的类名命名方法。用这种方法来表明这个 DOM 元素和 JavaScript 代码的关联。

<div class="site-navigation js-site-navigation">
</div>
<script>
    //the Javasript code
    const nav = document.querySelector('.js-site-navigation')
</script>
1
2
3
4
5
6

参考

BEM的定义

CSS 初始化

初始化的原因

由于浏览器兼容性的原因,不同浏览器 HTML 标签的默认值也有所不同;
比如:body 标签有默认的外边距 margin;ul 标签有默认的小黑点和内边距 padding 等等;
如果对标签样式不做初始化,那不同浏览器解析出来的样式将会有差异,给前端er 布局带来很多困扰,这不是我们期望看到的结果;同时,对标签做初始化赋值,也会降低代码冗余,加大开发效率。

目前有 CSS Reset 和 Normalize.css 两种方式来初始化浏览器标签 CSS 样式

CSS Reset 用通配符将浏览器所有标签某些样式进行初始化设置。

优点:使不同的标签的默认样式在不同浏览器表现一致,解决标签样式兼容问题,让前端er 更好的实现前端布局;
缺点:使标签失去了它们本身原有的属性样式;

Normalize.css

Normalize.css 文件的 github 下载地址: http://necolas.github.io/normalize.css/
Normalize.css 是为弥补 CSS Reset 的不足提出的,是 CSS Reset 的一套较好的替代方案。

优点:
  • 保护了有价值的默认值 - 当一个元素在不同的浏览器中有不同的默认值时,Normalize.css 会力求让这些样式保持一致并尽可能与现代标准相符合。
  • Normalize.css 修复了浏览器的bug - 修复了常见的桌面端和移动端浏览器的 bug。
  • Normalize.css 是模块化的 - 可选择性地移除掉某些永远不会用到部分。
  • Normalize.css 拥有详细的文档 - 具体优缺点详见链接:https://www.cnblogs.com/webpush/p/4974063.html
安装
npm install normalize.css
1

normalize.css v8.0.1 (加入中文字适配)

/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
 
/* Document
   ========================================================================== */
 
/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */
 
html {
  line-height: 1.15; /* 1 */
  -webkit-text-size-adjust: 100%; /* 2 */
}
 
/* Sections
   ========================================================================== */
 
/**
 * Remove the margin in all browsers.
 * add Chinese font (结合百度跟腾讯)
 */
 
body {
  margin: 0;
  font-family: arial, 'Hiragino Sans GB', 'Microsoft Yahei', 'PingFang SC', Avenir, 'Segoe UI', STHeiti, 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', 微软雅黑, 宋体, Tahoma, Arial, Helvetica, sans-serif;
}
 
/**
 * Render the `main` element consistently in IE.
 */
 
main {
  display: block;
}
 
/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */
 
h1 {
  font-size: 2em;
  margin: 0.67em 0;
}
 
/* Grouping content
   ========================================================================== */
 
/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */
 
hr {
  box-sizing: content-box; /* 1 */
  height: 0; /* 1 */
  overflow: visible; /* 2 */
}
 
/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
 
pre {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}
 
/* Text-level semantics
   ========================================================================== */
 
/**
 * Remove the gray background on active links in IE 10.
 */
 
a {
  background-color: transparent;
}
 
/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
 */
 
abbr[title] {
  border-bottom: none; /* 1 */
  text-decoration: underline; /* 2 */
  text-decoration: underline dotted; /* 2 */
}
 
/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */
 
b,
strong {
  font-weight: bolder;
}
 
/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
 
code,
kbd,
samp {
  font-family: monospace, monospace; /* 1 */
  font-size: 1em; /* 2 */
}
 
/**
 * Add the correct font size in all browsers.
 */
 
small {
  font-size: 80%;
}
 
/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */
 
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
 
sub {
  bottom: -0.25em;
}
 
sup {
  top: -0.5em;
}
 
/* Embedded content
   ========================================================================== */
 
/**
 * Remove the border on images inside links in IE 10.
 */
 
img {
  border-style: none;
}
 
/* Forms
   ========================================================================== */
 
/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */
 
button,
input,
optgroup,
select,
textarea {
  font-family: inherit; /* 1 */
  font-size: 100%; /* 1 */
  line-height: 1.15; /* 1 */
  margin: 0; /* 2 */
}
 
/**
 * Show the overflow in IE.
 * 1. Show the overflow in Edge.
 */
 
button,
input { /* 1 */
  overflow: visible;
}
 
/**
 * Remove the inheritance of text transform in Edge, Firefox, and IE.
 * 1. Remove the inheritance of text transform in Firefox.
 */
 
button,
select { /* 1 */
  text-transform: none;
}
 
/**
 * Correct the inability to style clickable types in iOS and Safari.
 */
 
button,
[type="button"],
[type="reset"],
[type="submit"] {
  -webkit-appearance: button;
}
 
/**
 * Remove the inner border and padding in Firefox.
 */
 
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
  border-style: none;
  padding: 0;
}
 
/**
 * Restore the focus styles unset by the previous rule.
 */
 
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
  outline: 1px dotted ButtonText;
}
 
/**
 * Correct the padding in Firefox.
 */
 
fieldset {
  padding: 0.35em 0.75em 0.625em;
}
 
/**
 * 1. Correct the text wrapping in Edge and IE.
 * 2. Correct the color inheritance from `fieldset` elements in IE.
 * 3. Remove the padding so developers are not caught out when they zero out
 *    `fieldset` elements in all browsers.
 */
 
legend {
  box-sizing: border-box; /* 1 */
  color: inherit; /* 2 */
  display: table; /* 1 */
  max-width: 100%; /* 1 */
  padding: 0; /* 3 */
  white-space: normal; /* 1 */
}
 
/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */
 
progress {
  vertical-align: baseline;
}
 
/**
 * Remove the default vertical scrollbar in IE 10+.
 */
 
textarea {
  overflow: auto;
}
 
/**
 * 1. Add the correct box sizing in IE 10.
 * 2. Remove the padding in IE 10.
 */
 
[type="checkbox"],
[type="radio"] {
  box-sizing: border-box; /* 1 */
  padding: 0; /* 2 */
}
 
/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */
 
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}
 
/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */
 
[type="search"] {
  -webkit-appearance: textfield; /* 1 */
  outline-offset: -2px; /* 2 */
}
 
/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */
 
[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}
 
/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */
 
::-webkit-file-upload-button {
  -webkit-appearance: button; /* 1 */
  font: inherit; /* 2 */
}
 
/* Interactive
   ========================================================================== */
 
/*
 * Add the correct display in Edge, IE 10+, and Firefox.
 */
 
details {
  display: block;
}
 
/*
 * Add the correct display in all browsers.
 */
 
summary {
  display: list-item;
}
 
/* Misc
   ========================================================================== */
 
/**
 * Add the correct display in IE 10+.
 */
 
template {
  display: none;
}
 
/**
 * Add the correct display in IE 10.
 */
 
[hidden] {
  display: none;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351

CSS 布局框架

CSS 布局大家熟知的有 Flex 布局,我们可以把它看成是一维布局。另有一种强大的二维网格布局 Grid,Grid 布局远比 Flex 布局强大。
Susy 是前端布局的一个极佳辅助工具,可用它来搭建任何需要的栅格布局,相比 Bootstrap 更灵活方便。
Susy 中有一系列的默认参数,用来初始化项目

Flex 布局

Flex 布局----Flexible box layout
可将任何元素指定为 Flex 布局,不管此元素是块元素还是行内元素

当元素设为 Flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效。

HTML.png

icon font

采用阿里图标图标库

stylelint

// 不要使用已被 autoprefixer 支持的浏览器前缀
 'media-feature-name-no-vendor-prefix': true,
 'at-rule-no-vendor-prefix': true,
 'selector-no-vendor-prefix': true,
 'property-no-vendor-prefix': true,
 'value-no-vendor-prefix': true,
 // 字体系列中命名时带引号
 'font-family-name-quotes': 'always-where-recommended',
 // 使用数字或命名的 (可能的情况下) font-weight 值
 'font-weight-notation': 'numeric',
 // 在函数的逗号之后要求有一个换行符或禁止有空白
 'function-comma-newline-after': null,
 // 在函数的括号内要求有一个换行符或禁止有空白
 'function-parentheses-newline-inside': null,
 // url 使用引号
 'function-url-quotes': 'never',
 // 禁止小于 1 的小数的前导 0
 'number-leading-zero': 'always',
 // 字符串使用单引号
 'string-quotes': 'single',
 // 要求选择器列表的逗号之前有一个换行符
 'selector-list-comma-newline-before': 'never-multi-line',
 // 在媒体查询的逗号之前禁止有一换行
 'media-query-list-comma-newline-before': 'never-multi-line',
 // 缩进
 'indentation': 2,
 // 禁止低优先级的选择器出现在高优先级的选择器之后
 'no-descending-specificity': null,
 // 不允许空的来源
 'no-empty-source': null,
 // 禁止缺少文件末尾的换行符
 'no-missing-end-of-source-newline': null,
 'font-family-no-missing-generic-family-keyword':null,
 // 颜色值为小写字母(stylelint-config-standard)
 // "color-hex-case": "lower",
 // 颜色值不能为无效值(stylelint-config-standard)
 // "color-no-invalid-hex": true,
 // 禁止在数量尾随零
 "number-no-trailing-zeros": true,
 // 禁止单位零长度。
 "length-zero-no-unit": true,
 // 属性值小写
 "value-keyword-case": "lower",
 // 在值列表的逗号后指定一个换行符或禁止留有空格
 "value-list-comma-newline-after": "always-multi-line",
 // 不允许在简写属性冗余值
 "shorthand-property-no-redundant-values": true,
 // 为属性指定小写(stylelint-config-standard)
 // "property-case": "lower",
 // 不允许!important在关键帧声明
 "keyframe-declaration-no-important": true,
 // 不允许关闭括号前空一行(stylelint-config-standard)
 // "block-closing-brace-empty-line-before": "never",
 // 需要一个换行符关闭括号后的空白(stylelint-config-standard)
 "block-closing-brace-newline-after": "always",
 // 开括号的块之后需要新的一行(stylelint-config-standard)
 // "block-opening-brace-newline-after": "always-multi-line",
 // 指定一个模式类选择符,限制选择器名称写法
 "selector-class-pattern": "^[a-z]+([a-z0-9]?|[a-z0-9\\-\\_]*[a-z0-9])$",
 // 指定一个模式,id选择器,限制选择器名称写法
 "selector-id-pattern": "^[a-z]+([a-z0-9]?|[a-z0-9\\-\\_]*[a-z0-9])$",
 // 不允许at-rules不明
 "at-rule-no-unknown": null,
 // 允许嵌套的深度为 3
 "max-nesting-depth": 3,
 // 不允许重复的选择器
 "no-duplicate-selectors": true
 // 不允许行尾空白(stylelint-config-standard)
 // "no-eol-whitespace": true,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

Vue+Webpack 下配置 stylelint

使用 webpack 编译 ,接著安装

npm i -D stylelint-webpack-plugin
// or
yarn add -D stylelint-webpack-plugin
1
2
3

设置 build/webpack.dev.conf.js

// webpack.base.conf.js
const StyleLintPlugin = require('stylelint-webpack-plugin');
module.exports = {
  // ... 其它选项
  plugins: [
    new StyleLintPlugin({
      files: ['src/**/*.{vue,htm,html,css,sss,less,scss,sass}']
    })
  ]
}
1
2
3
4
5
6
7
8
9
10

vue-cli3下配置

本地安装@ascendancyy/vue-cli-plugin-stylelint

npm i -D  @ascendancyy/vue-cli-plugin-stylelint
// or
yarn add -D @ascendancyy/vue-cli-plugin-stylelint
1
2
3

vue-cli3的 vue.config.js 需添加以下配置

pluginOptions: {
  lintStyleOnBuild: true, // 添加了插件(@ascendancyy/vue-cli-plugin-stylelint), 所以需要配置
  stylelint: {
    fix: true, // boolean (default: true)
    files: ['src/**/*.vue', 'src/assets/styles/*.l?(e|c)ss'] // string | [string] (default: ['src/**/*.{vue,htm,html,css,sss,less,scss}'])
    // formatter: () => { } // function (default: require('stylelint-codeframe-formatter'))
    // etc...
  }
}
1
2
3
4
5
6
7
8
9

Vue 文件下进行 stylelint 校验

安装插件

npm i -D stylelint-processor-html
// or
yarn add -D stylelint-processor-html
1
2
3

修改配置文件 stylelint.config.js

module.exports = {
    'defaultSeverity': 'error',
    'processors': ["stylelint-processor-html"],
    'extends': [ 'stylelint-config-standard' ],
    'plugins': [ 'stylelint-scss' ],
    'rules': {
        // 不要使用已被 autoprefixer 支持的浏览器前缀
        'media-feature-name-no-vendor-prefix': true,
        'at-rule-no-vendor-prefix': true,
        'selector-no-vendor-prefix': true,
        'property-no-vendor-prefix': true,
        'value-no-vendor-prefix': true
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

加上 Stylelint 规则

module.exports = {
  processors: ["stylelint-processor-html"],
  extends: ["stylelint-config-standard"],
  plugins: ["stylelint-scss","stylelint-order"], // stylelint-order是CSS属性排序插件
  rules: {
    // "color-hex-case": "lower", // 颜色值为小写字母(stylelint-config-standard)
    // "color-no-invalid-hex": true, // 颜色值不能为无效值(stylelint-config-standard)
    "font-family-name-quotes": "always-where-recommended", // 字体系列中命名时带引号
    "function-url-quotes": "always", // 地址一定要写引号
    "number-leading-zero": "never", // 要求或分数低于1的数字禁止前导零
    "number-no-trailing-zeros": true, // 禁止在数量尾随零
    "string-quotes": "double", // 指定字串,双引号
    "length-zero-no-unit": true, // 禁止单位零长度。
    "value-keyword-case": "lower", // 指定小写关键字的值
    "value-list-comma-newline-after": "always-multi-line",// 在值列表的逗号后指定一个换行符或禁止留有空格
    "shorthand-property-no-redundant-values": true, // 不允许在简写属性冗余值
    // "property-case": "lower", // 为属性指定小写(stylelint-config-standard)
    "keyframe-declaration-no-important": true, // 不允许!important在关键帧声明
    // "block-closing-brace-empty-line-before": "never", // 不允许关闭括号前空一行(stylelint-config-standard)
    // "block-closing-brace-newline-after": "always", // 需要一个换行符关闭括号后的空白(stylelint-config-standard)
    // "block-opening-brace-newline-after": "always-multi-line", // 开括号的块之后需要新的一行(stylelint-config-standard)
    "selector-class-pattern": "^[a-z]+([a-z0-9]?|[a-z0-9\\-\\_]*[a-z0-9])$", // 指定一个模式类选择符,限制选择器名称写法
    "selector-id-pattern": "^[a-z]+([a-z0-9]?|[a-z0-9\\-\\_]*[a-z0-9])$", // 指定一个模式,id选择器,限制选择器名称写法
    "value-keyword-case": "lower", // 属性值小写
    "no-empty-source": null, // 不允许空的来源
    "at-rule-no-unknown": null, // 不允许at-rules不明
    // "indentation": 2, // 指定缩进(stylelint-config-standard)
    "max-nesting-depth": 3, // 允许嵌套的深度为3
    "no-duplicate-selectors": true // 不允许重复的选择器
    // "no-eol-whitespace": true, // 不允许行尾空白(stylelint-config-standard)
    // "no-invalid-double-slash-comments": true // 不允许双斜杠注释(/ /…)不支持CSS(stylelint-config-standard)
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

stylelint 搭配 stylelint-order,可以校验 CSS的属性顺序

安装stylelint-order

npm i -D stylelint-order
// or
yarn add -D stylelint-order
1
2
3

在"stylelint.config.js"配置文件新增stylelint-order插件,通过"order/properties-order"定义顺序

module.exports = {
  processors: ["stylelint-processor-html"],
  extends: ["stylelint-config-standard"],
  plugins: ["stylelint-scss","stylelint-order"], // stylelint-order是CSS属性排序插件
  rules: {
    // "color-hex-case": "lower", // 颜色值为小写字母(stylelint-config-standard)
    // "color-no-invalid-hex": true, // 颜色值不能为无效值(stylelint-config-standard)
    "font-family-name-quotes": "always-where-recommended", // 字体系列中命名时带引号
    "function-url-quotes": "always", // 地址一定要写引号
    "number-leading-zero": "never", // 要求或分数低于1的数字禁止前导零
    "number-no-trailing-zeros": true, // 禁止在数量尾随零
    "string-quotes": "double", // 指定字串,双引号
    "length-zero-no-unit": true, // 禁止单位零长度。
    "value-keyword-case": "lower", // 指定小写关键字的值
    "value-list-comma-newline-after": "always-multi-line",// 在值列表的逗号后指定一个换行符或禁止留有空格
    "shorthand-property-no-redundant-values": true, // 不允许在简写属性冗余值
    // "property-case": "lower", // 为属性指定小写(stylelint-config-standard)
    "keyframe-declaration-no-important": true, // 不允许!important在关键帧声明
    // "block-closing-brace-empty-line-before": "never", // 不允许关闭括号前空一行(stylelint-config-standard)
    // "block-closing-brace-newline-after": "always", // 需要一个换行符关闭括号后的空白(stylelint-config-standard)
    // "block-opening-brace-newline-after": "always-multi-line", // 开括号的块之后需要新的一行(stylelint-config-standard)
    "selector-class-pattern": "^[a-z]+([a-z0-9]?|[a-z0-9\\-\\_]*[a-z0-9])$", // 指定一个模式类选择符,限制选择器名称写法
    "selector-id-pattern": "^[a-z]+([a-z0-9]?|[a-z0-9\\-\\_]*[a-z0-9])$", // 指定一个模式,id选择器,限制选择器名称写法
    "value-keyword-case": "lower", // 属性值小写
    "no-empty-source": null, // 不允许空的来源
    "at-rule-no-unknown": null, // 不允许at-rules不明
    // "indentation": 2, // 指定缩进(stylelint-config-standard)
    "max-nesting-depth": 3, // 允许嵌套的深度为3
    "no-duplicate-selectors": true, // 不允许重复的选择器
    // "no-eol-whitespace": true, // 不允许行尾空白(stylelint-config-standard)
    // "no-invalid-double-slash-comments": true // 不允许双斜杠注释(/ /…)不支持CSS(stylelint-config-standard)
    "order/order": [ // 指定声明块内的内容顺序
      ["custom-properties", "declarations"], {
        "disableFix": true
      }
    ],
    "order/properties-order": [ // 指定声明块内属性的字母顺序
      'position',
      'top',
      'right',
      'bottom',
      'left',
      'z-index',
      'display',
      'float',
      'width',
      'height',
      'max-width',
      'max-height',
      'min-width',
      'min-height',
      'padding',
      'padding-top',
      'padding-right',
      'padding-bottom',
      'padding-left',
      'margin',
      'margin-top',
      'margin-right',
      'margin-bottom',
      'margin-left',
      'margin-collapse',
      'margin-top-collapse',
      'margin-right-collapse',
      'margin-bottom-collapse',
      'margin-left-collapse',
      'overflow',
      'overflow-x',
      'overflow-y',
      'clip',
      'clear',
      'font',
      'font-family',
      'font-size',
      'font-smoothing',
      'osx-font-smoothing',
      'font-style',
      'font-weight',
      'hyphens',
      'src',
      'line-height',
      'letter-spacing',
      'word-spacing',
      'color',
      'text-align',
      'text-decoration',
      'text-indent',
      'text-overflow',
      'text-rendering',
      'text-size-adjust',
      'text-shadow',
      'text-transform',
      'word-break',
      'word-wrap',
      'white-space',
      'vertical-align',
      'list-style',
      'list-style-type',
      'list-style-position',
      'list-style-image',
      'pointer-events',
      'cursor',
      'background',
      'background-attachment',
      'background-color',
      'background-image',
      'background-position',
      'background-repeat',
      'background-size',
      'border',
      'border-collapse',
      'border-top',
      'border-right',
      'border-bottom',
      'border-left',
      'border-color',
      'border-image',
      'border-top-color',
      'border-right-color',
      'border-bottom-color',
      'border-left-color',
      'border-spacing',
      'border-style',
      'border-top-style',
      'border-right-style',
      'border-bottom-style',
      'border-left-style',
      'border-width',
      'border-top-width',
      'border-right-width',
      'border-bottom-width',
      'border-left-width',
      'border-radius',
      'border-top-right-radius',
      'border-bottom-right-radius',
      'border-bottom-left-radius',
      'border-top-left-radius',
      'border-radius-topright',
      'border-radius-bottomright',
      'border-radius-bottomleft',
      'border-radius-topleft',
      'content',
      'quotes',
      'outline',
      'outline-offset',
      'opacity',
      'filter',
      'visibility',
      'size',
      'zoom',
      'transform',
      'box-align',
      'box-flex',
      'box-orient',
      'box-pack',
      'box-shadow',
      'box-sizing',
      'table-layout',
      'animation',
      'animation-delay',
      'animation-duration',
      'animation-iteration-count',
      'animation-name',
      'animation-play-state',
      'animation-timing-function',
      'animation-fill-mode',
      'transition',
      'transition-delay',
      'transition-duration',
      'transition-property',
      'transition-timing-function',
      'background-clip',
      'backface-visibility',
      'resize',
      'appearance',
      'user-select',
      'interpolation-mode',
      'direction',
      'marks',
      'page',
      'set-link-source',
      'unicode-bidi',
      'speak'
    ]
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

vue 项目中,使用 autoprefixer (非必要)

vue-cli的开发环境和生产环境都是使用了 postcss 的,并且配置是一样的

修改 webpack.prod.conf.js ,解决项目打包前和打包后的 css 前缀不一致 (其实不太需要调整,针对有强迫症同学)

new OptimizeCSSPlugin({
     cssProcessorOptions: config.build.productionSourceMap
       ? { safe: true, map: { inline: false }, autoprefixer:false  }
       : { safe: true, autoprefixer:false  }
   }),
1
2
3
4
5

原因说明:
OptimizeCSSPlugin 里面依赖了 cssnano,而cssnano里面也有一个 autoprefixer 配置参数,它的作用是删除不必要的前缀(会误删在某些浏览器必要的前缀),这与 postcss 的 autoprefixer 效果冲突了,因此禁用它。现在打包出来的与我们设定的浏览器范围对应的前缀一致。

兼容大多数主流机型,在package.json里面找到 browserslist ,加上

"browserslist": [
   "> 1%",
   "last 2 versions",
   "not ie <= 8",
   "iOS >= 8",
   "Firefox >= 20",
   "Android > 4.4"
 ],
1
2
3
4
5
6
7
8

若使用 SCSS,需加入

安装 node-sass 和 sass-loader

npm install node-sass sass-loader --save-dev
// or
yarn add -D node-sass sass-loader
1
2
3

修改 webpack.base.config.js,在 module 里的rules中加上

{
   test: /\.scss$/,
   loaders: ["style", "css", "sass"]
},
1
2
3
4

vue 文件中的 style 使用 scss

<style rel="stylesheet/scss" lang="scss" scoped></style>
1

加入提交静态检测

install 安装 lint-staged 、husky

npm i -D lint-staged husky
// or
yarn add -D lint-staged husky
1
2
3

向 package.json 添加运行脚本 "precommit": "lint-staged",git commit 之前会跑 lint-staged

{
  "husky": {
    "hooks": {
        "pre-commit": "lint-staged"
    }
  }
}
1
2
3
4
5
6
7

修改 package.json 配置,(和 script 同层)

"lint-staged": {
   "src/**/*.{html,vue,css,sass,scss}": [
      "stylelint --fix",
      "git add"
    ]
},
1
2
3
4
5
6

完整如下:

{
  "husky": {
    "hooks": {
        "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "src/**/*.{html,vue,css,sass,scss}": [
      "stylelint --fix",
      "git add"
    ]
  },
  "devDependencies": {
    "husky": "^1.2.0",
    "lint-staged": "^8.1.0",
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Last Updated: 2019-8-14 6:29:41 PM