【前端规范】02.CSS代码规范(Stylelint+Vscode配置)

119 阅读7分钟

1.css的书写顺序到底会影响渲染性能吗

页面的渲染流程

渲染引擎首先通过网络获得所请求文档的内容,通常以8K分块的方式完成。下面是渲染引擎在取得内容之后的基本流程:

解析html以构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树

图片

  

这里先解释一下几个概念,方便大家理解:

DOM Tree:浏览器将HTML解析成树形的数据结构。

CSS Rule Tree:浏览器将CSS解析成树形的数据结构。

Render Tree: DOM和CSSOM合并后生成Render Tree。

layout: 有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系,从而去计算出每个节点在屏幕中的位置。

painting: 按照算出来的规则,通过显卡,把内容画到屏幕上。

reflow(回流):当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,内行称这个回退的过程叫 reflow。reflow 会从 这个 root frame 开始递归往下,依次计算所有的结点几何尺寸和位置。reflow 几乎是无法避免的。

现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引起浏览器的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲 染。

通常我们都无法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。\

repaint(重绘):改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变。

注意:

(1)display:none 的节点不会被加入Render Tree,而visibility: hidden 则会,所以,如果某个节点最开始是不显示的,设为display:none是更优的。

(2)display:none 会触发 reflow,而 visibility:hidden 只会触发 repaint,因为没有发现位置变化。

(3)有些情况下,比如修改了元素的样式,浏览器并不会立刻reflow 或 repaint 一次,而是会把这样的操作积攒一批,然后做一次 reflow,这又叫异步 reflow 或增量异步 reflow。但是在有些情况下,比如resize 窗口,改变了页面默认的字体等。对于这些操作,浏览器会马上进行 reflow。

举个栗子

width: 200px;
height: 200px;
position: absolute;

按照上文介绍的页面的渲染过程,这段代码在运行到postion的时候就可能会reflow(回流),进而导致页面进行repaint(重绘),所以调整css的书写顺序能够避免这一过程

position: absolute;
width: 200px;
height: 200px;

不过现代浏览器的引擎和性能相比于几年前有很大的提升,所以css的写作顺序对于渲染性能问题上几乎可以忽略不计= =。不过养成好的书写规范仍是至关重要的好习惯!

2.css的书写顺序

建议遵循以下顺序:

  1. 布局定位属性:display / position / float / clear / visibility / overflow(建议 display 第一个写,毕竟关系到模式)
  2. 自身属性:width / height / margin / padding / border / background
  3. 文字样式:font-family   font-size   font-style   font-weight   font-varient   color
  4. 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
  5. 其他属性(CSS3) :content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradient …
    display: block;
    position: relative;
    float: left;
    width: 100px;
    height: 100px;
    margin: 0 10px;
    padding: 20px 0;
    font-size:12px;
    color: #333;
    background: rgba(0,0,0,.5);
    border-radius: 10px;

3.使用stylelint规范css代码

开源比较流行的 CSS lint 方案:Csslint、SCSS-Lint、Stylelint,而Stylelint是基于AST 的方式扩展CSS,除原生CSS 语法,也支持 SCSS、Less 这类预处理器,并且有非常多的第三方插件,因此选择了Stylelint作为CSS Lint的工具。

Stylelint 优点

  • 其支持 Less、Sass 这类预处理器
  • 在社区活跃度上,有非常多的 第三方插件
  • 在 Facebook,Github,WordPress 等公司得到实践,能够覆盖很多场景

安装依赖

  • stylelint — 运行工具
  • stylelint-config-standard — stylelint的推荐配置(如果想使用airbnb或prettier的规范,也可以将stylelint-config-standard改为stylelint-config-airbnb或stylelint-config-prettier)
  • stylelint-order — 排序插件(先写定位,再写盒模型,再写内容区样式,最后写 CSS3 相关属性)
  • stylelint-commponent 解析依赖
  • stylelint-config-prettier 关闭所有不必要的或可能与Prettier冲突的规则
  • stylelint-config-styled-components 共享stylelint的配置 校验styled-component

配置Stylelint
Stylelint的配置方式有以下几种:

  • 在package.json中添加stylelint属性并添加规则
  • 在.stylelintrc文件中指定,.stylelintrc文件支持添加一个文件扩展名来区分 JSON,YAML 或 JS 格式,如创建.stylelintrc.json、.stylelintrc.yaml、.stylelintrc.yml或.stylelintrc.js文件
  • 在stylelint.config.js文件中指定,该文件将会exports一个配置对象

采用.stylelintrc.js 进行配置

3.1stylelint 配置项

  • plugins //数组,可以是一个 npm 模块名,一个绝对路径,或一个相对于要调用的配置文件的路径
  • extends //数组,该配置项允许我们extend一个已存在的配置文件(无论是你自己的还是第三方的配置),当一个配置继承了里一个配置,它将会添加自己的属性并覆盖原有的属性
  • rules //对象,它告诉Stylelint该检查什么,该怎么报错
  • ignoreFiles //数组,配置忽略的文件路劲

参考配置如下:

module.exports = {
  extends: [
    'stylelint-config-standard',
    'stylelint-config-prettier',
    'stylelint-config-html/vue',
    'stylelint-config-recommended-vue/scss',
    'stylelint-config-recommended-less',
    'stylelint-config-recommended-scss',
 
  ],
  plugins: ['stylelint-order'],
  overrides: [
    {
      "files": ["**/*.vue"],
      "customSyntax": "postcss-html"
    }
  ],
  ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts', '**/*.json', ],
  rules: {
    indentation: 2,
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep', ':deep']
      }
    ],
    'number-leading-zero': 'always',
    'no-descending-specificity': null,
    'function-url-quotes': 'always',
    'string-quotes': 'single',
    'unit-case': null,
    'color-hex-case': 'lower',
    'color-hex-length': 'long',
    'rule-empty-line-before': 'never',
    'font-family-no-missing-generic-family-keyword': null,
    'selector-type-no-unknown': null,
    'block-opening-brace-space-before': 'always',
    'at-rule-no-unknown': null,
    'no-duplicate-selectors': null,
    'property-no-unknown': null,
    'no-empty-source': null,
    'selector-class-pattern': null,
    'keyframes-name-pattern': null,
    'selector-pseudo-class-no-unknown': [
      true,
      { ignorePseudoClasses: ['global', 'deep'] }
    ],
    'function-no-unknown': null,
    'order/properties-order': [
      'position',
      'top',
      'right',
      'bottom',
      'left',
      'z-index',
      'display',
      'justify-content',
      'align-items',
      'float',
      'clear',
      'overflow',
      'overflow-x',
      'overflow-y',
      'margin',
      'margin-top',
      'margin-right',
      'margin-bottom',
      'margin-left',
      'padding',
      'padding-top',
      'padding-right',
      'padding-bottom',
      'padding-left',
      'width',
      'min-width',
      'max-width',
      'height',
      'min-height',
      'max-height',
      'font-size',
      'font-family',
      'font-weight',
      'border',
      'border-style',
      'border-width',
      'border-color',
      'border-top',
      'border-top-style',
      'border-top-width',
      'border-top-color',
      'border-right',
      'border-right-style',
      'border-right-width',
      'border-right-color',
      'border-bottom',
      'border-bottom-style',
      'border-bottom-width',
      'border-bottom-color',
      'border-left',
      'border-left-style',
      'border-left-width',
      'border-left-color',
      'border-radius',
      'text-align',
      'text-justify',
      'text-indent',
      'text-overflow',
      'text-decoration',
      'white-space',
      'color',
      'background',
      'background-position',
      'background-repeat',
      'background-size',
      'background-color',
      'background-clip',
      'opacity',
      'filter',
      'list-style',
      'outline',
      'visibility',
      'box-shadow',
      'text-shadow',
      'resize',
      'transition'
    ]
  }
};

3.2 执行和忽略Stylelint检查

执行Stylelint检查

// 对某个文件进行检查
stylelint "src/App.vue" --fix

// 对指定后缀名的文件进行检查
stylelint "src/*.{vue,less,postcss}" --fix
    

忽略Stylelint检查

1.使用注释禁用规则

使用/* stylelint-disable */,可以在代码片段禁用所有规则或禁用特定规则。

/* stylelint-disable */
a {}
/* stylelint-enable */

/* stylelint-disable selector-no-id, declaration-no-important  */
#id {
  color: pink !important;
}
/* stylelint-enable */

使用/* stylelint-disable-line */,可以在个别行上禁用规则。

#id { /* stylelint-disable-line */
  color: pink !important; /* stylelint-disable-line declaration-no-important */
}

使用/* stylelint-disable-next-line */,可以在下一行禁用规则。

#id {
  /* stylelint-disable-next-line declaration-no-important */
  color: pink !important;
}

2.创建.stylelintignore忽略文件检查

//.stylelintignore
node_modules
pont
client/api

4.Vscode插件使用

在vscode中安装以下插件:

{
     //开启自动修复
     "editor.codeActionsOnSave": {
      "source.fixAll": true, // 开启自动修复
      "source.fixAll.stylelint": true, // 开启stylelint自动修复
  },
  // 配置stylelint检查的文件类型范围
  "stylelint.validate": [
      "css",
      "less",
      "postcss",
      "scss",
      "sass",
      "vue"
  ],
  "stylelint.enable": true,
  "css.validate": false,
  "less.validate": false,
  "scss.validate": false,
}

5.参考