目录

1.设计规范
1.1.目录设计
1.2.变量命名
1.3.界面布局
1.4.设计模式
1.5.文档设计
2.编码规范
3.插件使用(以vscode为例)
4.参考资源
5.总结

写在前面

1.设计规范

1.1.目录设计

目录结构这一块设计参照vue脚手架做为一个参考的基础,主要还是要注意命名和结构组织管理。
  • 项目命名
    全部采用小写方式, 以中划线分隔。

    正例:mall-management-system/mall_management-system

    反例: mallManagementSystem

  • 目录命名
    全部采用小写方式, 以中划线分隔,有复数结构时,要采用复数命名法, 缩写不用复数

    正例: scripts / styles / components / images / utils / layouts / demo-styles / demo-scripts / img / doc / demo_scripts

    反例: script / style / demoStyles / imgs / docs

    【特殊】VUE 的项目中的 components 中的组件目录,使用 kebab-case 命名

    正例: head-search / page-loading / authorized / notice-icon

    反例: HeadSearch / PageLoading

    【特殊】VUE 的项目中的除 components 组件目录外的所有目录也使用 kebab-case 命名
    正例: page-one / shopping-car / user-management

    反例: ShoppingCar / UserManagement
    注:不管参考哪种命名方式,最重要是要规则统一

   ├── index.html                      入口页面
    ├── build                            构建脚本目录
    │   ├── build-server.js                 运行本地构建服务器,可以访问构建后的页面
    │   ├── build.js                        生产环境构建脚本
    │   ├── dev-client.js                   开发服务器热重载脚本,主要用来实现开发阶段的页面自动刷新
    │   ├── dev-server.js                   运行本地开发服务器
    │   ├── utils.js                        构建相关工具方法
    │   ├── webpack.base.conf.js            wabpack基础配置
    │   ├── webpack.dev.conf.js             wabpack开发环境配置
    │   └── webpack.prod.conf.js            wabpack生产环境配置
    ├── config                          项目配置
    │   ├── dev.env.js                      开发环境变量
    │   ├── index.js                        项目配置文件
    │   ├── prod.env.js                     生产环境变量
    │   └── test.env.js                     测试环境变量
    ├── mock                            mock数据目录
    │   └── hello.js
    ├── package.json                    npm包配置文件,里面定义了项目的npm脚本,依赖包等信息
    ├── src                             项目源码目录    
    │   ├── main.js                         入口js文件
    │   ├── app.vue                         根组件
    │   ├── components                      公共组件目录
    │   │   └── title.vue
    │   ├── assets                          资源目录,这里的资源会被wabpack构建
    │   │   └── images
    │   │       └── logo.png
    │   ├── routes                          前端路由
    │   │   └── index.js
    │   ├── store                           应用级数据(state)
    │   │   └── index.js
    │   └── views                           页面目录
    │       ├── hello.vue
    │       └── notfound.vue
    ├── static                          纯静态资源,不会被wabpack构建。
    └── test                            测试文件目录(unit&e2e)
        └── unit                            单元测试
            ├── index.js                        入口脚本
            ├── karma.conf.js                   karma配置文件
            └── specs                           单测case目录
                └── Hello.spec.js

1.2.变量命名

网上有很多优秀的命名方案,可以参考看看,这里我只是选取比较关键的基础原则。
  • 注意词性
    普通变量/属性使用用名词

    var person = {
        name: 'Frank'
    }
    var student = {
        grade: 3,
        class: 2
    }

    bool变量/属性用形容词或者be动词或者情态动词或者hasX

    var person = {
        dead: false, // 如果是形容词,前面就没必要加 is,比如isDead 就很废话
        canSpeak: true, //情态动词有 can、should、will、need 等,情态动词后面接动词
        isVip: true, // be 动词有 is、was 等,后面一般接名词
        hasChildren: true, // has 加名词
    }

    普通函数/方法用动词开头

    var person = {
        run(){}, // 不及物动词
        drinkWater(){}, // 及物动词
        eat(foo){}, // 及物动词加参数(参数是名词)
    }

    回调、钩子函数用介词开头,或用动词的现在完成时态

    var person = {
        beforeDie(){},
        afterDie(){},
        // 或者
        willDie(){}
        dead(){} // 这里跟 bool 冲突,你只要不同时暴露 bool dead 和函数 dead 就行,怕冲突就用上面的 afterDie
    }
    button.addEventListener('click', onButtonClick)
    var component = {
        beforeCreate(){},
        created(){},
        beforeMount(){},
        mounted(){},
        beforeUpdate(){},
        updated(){},
        activated(){},
        deactivated(){},
        beforeDestroy(){},
        destroyed(){},
        errorCaptured(){}
    }

    容易混淆的地方加前缀
    div1.classList.add('active') // DOM 对象
    div2.addClass('active') // jQuery 对象
    不如改成
    domDiv1 或 elDiv1.classList.add('active')
    $div2.addClass('active')
    属性访问器函数可以用名词
    $div.text() // 其实是 $div.getText()
    $div.text('hi') // 其实是 $div.setText('hi')

  • 注意一致性
    介词一致性
    如果你使用了 before + after,那么就在代码的所有地方都坚持使用
    如果你使用了 before + 完成时,那么就坚持使用
    如果你改来改去,就「不一致」了,不一致将导致「不可预测」
    顺序一致性
    比如 updateContainerWidth 和 updateHeightOfContainer 的顺序就令人很别扭,同样会引发「不可预测」
    表里一致性
    函数名必须完美体现函数的功能,既不能多也不能少。
    比如

    function getSongs(){
        return $.get('/songs).then((response){
            div.innerText = response.songs
        })
    }

    就违背了表里一致性,getSongs 表示获取歌曲,并没有暗示这个函数会更新页面,但是实际上函数更新了 div,这就是表里不一,正确的 写法是

    要么纠正函数名

    
    function getSongsAndUpdateDiv(){
        return $.get('/songs).then((response){
            div.innerText = response.songs
        })
    }

    要么写成两个函数

    function getSongs(){
        return $.get('/songs)
    }
    function updateDiv(songs){
        div.innerText = response.songs
    }
    getSongs().then((response)=>{
        updateDiv(response.songs)
    })
  • 时间一致性
    有可能随着代码的变迁,一个变量的含义已经不同于它一开始的含义了,这个时候你需要及时改掉这个变量的名字。
    这一条是最难做到的,因为写代码容易,改代码难。如果这个代码组织得不好,很可能会出现牵一发而动全身的情况(如全局变量就很难改)
    很多优秀的框架或者代码,有很多优秀的编码规范,我们可以多参考多学习,灵活运用到实际的项目开发中。

1.3.界面布局

web端界面设计布局方案:参考elementUIweb端UI框架设计。
移动端的界面布局设计方案:参考Vant有赞移动端UI框架设计。

1.4.设计模式

  • 发布订阅模式
    以睿云的项目架构为例,每个患者信息根据不同就诊医院可能存在不同层级的组件和页面模块,并且在不同父组件下面的子组件或者孙组件之间传递数据的。
    image.png
    可以看出,图中的数据传递十分复杂,并且不够直观,代码也显得非常臃肿,难以维护。显然仅仅用单向数据流或者双向绑定父子组件间的透传数据,并不能很好的满足一些复杂多变的项目需求。
    image.png
    利用发布订阅模式进行公用组件进行全局管理,整个代码结构会非常清晰直观,维护起来也相对方便。然后,无论子组件还是父组件都能通过这样来传递数据,所有的操作都在一个eventbus事件中心进行,简化其中多层组件的传递的复杂性和不确定性。

    this.eventBus.$emit() // 发布
    this.eventBus.$on() // 订阅
    this.eventBus.$off() // 取消订阅

    可以根据项目的实际情况,选择开发模式,没有最好的设计模式,只有最适合实际项目才能大大简化项目复杂性,提高开发效率。

  • 表驱动编程
    所有一一对应的关系都可以用表来做,一般涉及相关多个if-else等逻辑分支处理,分支最多不要超过三个。不仅代码冗余,而且不够清晰直观。switch...case虽然可以一定程度解决这样问题,但是当逻辑分支继续增加,代码过长,还是避免不了相关的问题产生。

使用表驱动进行代码改写:

const  types_table={
'appointmentSummary':fn1,
'patientDiseaseInfo':fn2,
'patientInfo':fn3,
'questionnaireFiller':fn4
...
}
types_table[type]()

根据不同判断条件对应不同的执行逻辑,将其组织成一个一个的函数,实现逻辑和代码实现的一个抽离。整个代码开发,非常的整洁清晰,而且易于扩展,最关键的是提高了代码的可读性。

1.5.文档设计

jsdoc用于编写前端组件说明的js注释库,可以根据相关的注释说明,生成相应的组件开发的文档说明。有效减少开发人员之间的开发沟通成本,提高开发效率。

/**
 * RuiJin类存储一位客人的名字,并打招呼。
 */
class RuiJin {
  /**
   * 主要是解释data里面关于瑞金医院的评估报告js的文件
   * 
   * @param {Object} patientInfo 评估报告的患者的基本信息数据
   * @param {Boolean} showPanel1 查看报告界面的第一个tab项的显隐
   * @param {Boolean} showPanel2 查看报告界面的第二个tab项的显隐
   * @param {Object} formData 新增模块的开关期和评分的选择表格项
   * @param {String} evaluationResult1 当报告结论需要两页展示时,用于存储第二页的报告检查结论。
   * @param {String} evaluationId 存储当前报告的id项
   * @param {Boolean} printPageShow 是否显示超过第二页的打印页
   */
  constructor() {
    this.patientInfo = {}
    this.maGaitExport = {
      summaryDatas: [],
      walkDetails: [],
    }
    this.summaryData = []  // 概要
    this.statis = {
      walk: [], // 行走过程
      turn: [], // 转向过程
      fog: [], // 冻结详情
    }
    this.patientGaitModel = {}
    this.FogRecogn = {
      FogResults: {}, // 冻结步态概况
      FogDetails: [], // 冻结步态详情
    }
    this.isEdit = false // 是否处于编辑状态
    this.PressureRightEnd = [] // 右后脚跟压强
    this.expandState = [true, true, true, true] // 展开收起状态
    this.showScrollBtn = false
    this.canEdit = false // 检查结论是否可以编辑
    this.isShowDialog = false // 是否显示编辑医生弹窗

    this.currentTabIndex = 1 // 0 运动分析报告 1 冻结指数
    this.freezeExpandState = [true, true, true] // 冻结步态展开收起状态
    this.evaluationResult1 = '闪烁'
    this.dialog1 = true//检查结论dialog说明
    this.diagnostician = ''//诊断医生
    this.tug6CheckItemList = []//参数项list
    this.fogDetailsEmptyCount = 0
    this.status = ''
    this.showPanel1 = false
    this.showPanel2 = true
    this.formData = {
      switchType: '',
      isSynchroScore: ''
    }
    this.evaluationResult1 = ''
    this.evaluationId = ''
    this.printPageShow = true
  }
  /**
   * 筛选出报告里面所有检查项的实验时长的最大值
   * 
   */
  MaxSummaryCheckTime () {
    const allCheckTimes = reportData.maGaitExport.summaryDatas.map(item => Math.ceil((item && item.TrialTime) || 0))
    if (allCheckTimes.length === 0) {
      return 0
    } else {
      return Math.max(...allCheckTimes)
    }
  }
  /**
   * 用于判断打印界面是否需要展示两页
   * 首先通过\n换行符来切分判断,存在多少,在去判断在\n的每一段存在多少行
   * 通过一行以48列为基准进行计算。
   * 
   */
  disatibutePages () {
    const colsLength = Math.ceil(this.patientGaitModel.evaluationResult.length / 48)
    const rowsLength = this.patientGaitModel.evaluationResult.split('\n').length - 1
    if (colsLength + rowsLength > 15) {
      this.evaluationResult1 = this.patientGaitModel.evaluationResult.split('\n').slice(rowsLength - colsLength).join('')
      this.patientGaitModel.evaluationResult = this.patientGaitModel.evaluationResult.split('\n').slice(0, rowsLength - colsLength).join('')
    }
    this.printPageShow = false
  }
}

2.编码规范

2.1.HTML规范

HTML 作为描述网页结构的超文本标记语言,在百度一直有着广泛的应用。本文档的目标是使 HTML 代码风格保持一致,容易被理解和被维护。

代码风格

缩进与换行

[强制] 使用 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符。

解释:
对于非 HTML 标签之间的缩进,比如 script 或 style 标签内容缩进,与 script 或 style 标签的缩进同级。

示例:

<style>
/* 样式内容的第一级缩进与所属的 style 标签对齐 */
ul {
    padding: 0;
}
</style>
<ul>
    <li>first</li>
    <li>second</li>
</ul>
<script>
// 脚本代码的第一级缩进与所属的 script 标签对齐
require(['app'], function (app) {
    app.init();
});
</script>
[建议] 每行不得超过 120 个字符。

解释:

过长的代码不容易阅读与维护。但是考虑到 HTML 的特殊性,不做硬性要求。

命名

[强制] class 必须单词全字母小写,单词间以 - 分隔。
[强制] class 必须代表相应模块或部件的内容或功能,不得以样式信息进行命名。

示例:

<!-- good -->
<div class="sidebar"></div>

<!-- bad -->
<div class="left"></div>
[强制] 元素 id 保证在页面唯一。

解释:

同一个页面中,不同的元素包含相同的 id,不符合 id 的属性含义。

[建议] id 建议单词全字母小写,单词间以 - 分隔。同项目必须保持风格一致。
[建议] idclass 命名,在避免冲突并描述清楚的前提下尽可能短。

示例:

<!-- good -->
<div id="nav"></div>
<!-- bad -->
<div id="navigation"></div>

<!-- good -->
<p class="comment"></p>
<!-- bad -->
<p class="com"></p>

<!-- good -->
<span class="author"></span>
<!-- bad -->
<span class="red"></span>
[强制] 禁止创建无样式信息的 class

解释:

不允许 class 只用于让 JavaScript 选择某些元素,class 应该具有明确的语义和样式。否则容易导致 CSS class 泛滥。

使用 id、属性选择作为js是更好的方式。

[强制] 同一页面,应避免使用相同的 nameid

解释:

IE 浏览器会混淆元素的 idname 属性, document.getElementById 可能获得不期望的元素。所以在对元素的 idname 属性的命名需要非常小心。

一个比较好的实践是,为 idname 使用不同的命名法。

示例:

<input name="foo">
<div id="foo"></div>
<script>
// IE6 将显示 INPUT
alert(document.getElementById('foo').tagName);
</script>
````


###  标签


#### [强制] 标签名必须使用小写字母。

示例:

<!-- good -->
<p>Hello StyleGuide!</p>

<!-- bad -->
<P>Hello StyleGuide!</P>


#### [强制] 对于无需自闭合的标签,不允许自闭合。

解释:

常见无需自闭合标签有 `input`、`br`、`img`、`hr` 等。


示例:

<!-- good -->
<input type="text" name="title">

<!-- bad -->
<input type="text" name="title" />


#### [强制] 对 `HTML5` 中规定允许省略的闭合标签,不允许省略闭合标签。

解释:

对代码体积要求非常严苛的场景,可以例外。比如:第三方页面使用的投放系统。

示例:

<!-- good -->
<ul>

<li>first</li>
<li>second</li>

</ul>

<!-- bad -->
<ul>

<li>first
<li>second

</ul>



#### [强制] 标签使用必须符合标签嵌套规则。

解释:

比如 `div` 不得置于 `p` 中,`tbody` 必须置于 `table` 中。

详细的标签嵌套规则参见[HTML DTD](http://www.cs.tut.fi/~jkorpela/html5.dtd)中的 `Elements` 定义部分。


#### [建议] HTML 标签的使用应该遵循标签的语义。(语义化)

解释:

下面是常见标签语义

- p - 段落
- h1,h2,h3,h4,h5,h6 - 层级标题
- strong,em - 强调
- ins - 插入
- del - 删除
- abbr - 缩写
- code - 代码标识
- cite - 引述来源作品的标题
- q - 引用
- blockquote - 一段或长篇引用
- ul - 无序列表
- ol - 有序列表
- dl,dt,dd - 定义列表


示例:

<!-- good -->
<p>Esprima serves as an important building block for some JavaScript language tools.</p>

<!-- bad -->
<div>Esprima serves as an important <span class="strong">building block</span> for some JavaScript language tools.</div>



#### [建议] 在 CSS 可以实现相同需求的情况下不得使用表格进行布局。

解释:

在兼容性允许的情况下应尽量保持语义正确性。对网格对齐和拉伸性有严格要求的场景允许例外,如多列复杂表单。


#### [建议] 标签的使用应尽量简洁,减少不必要的标签。

示例:

<!-- good -->
<img class="avatar" src="image.png">

<!-- bad -->
<span class="avatar">

<img src="image.png">

</span>


###  属性

#### [强制] 属性名必须使用小写字母。

示例:

<!-- good -->

...
<!-- bad --> ...
` #### [建议] 布尔类型的属性,建议不添加属性值。 示例: `(html) <input type="text" disabled> <input type="checkbox" value="1" checked> ` #### [建议] 自定义属性建议以 xxx- 为前缀,推荐使用 data-。 解释: 使用前缀有助于区分自定义属性和标准定义的属性。 示例: `(html) <ol data-ui-type="Select"></ol> ` ## 通用 ### DOCTYPE #### [强制] 使用 HTML5doctype 来启用标准模式,建议使用大写的 DOCTYPE。 示例: `(html) <!DOCTYPE html> ` #### [建议] 启用 IE Edge 模式。 示例: `(html) <meta http-equiv="X-UA-Compatible" content="IE=Edge"> ` #### [建议] 在 html 标签上设置正确的 lang 属性。 解释: 有助于提高页面的可访问性,如:让语音合成工具确定其所应该采用的发音,令翻译工具确定其翻译语言等。 示例: `(html) <html lang="zh-CN"> ` ### 编码 #### [强制] 页面必须使用精简形式,明确指定字符编码。指定字符编码的 meta 必须是 head 的第一个直接子元素。 解释: 见 HTML5 Charset能用吗 一文。 示例: `(html) <html> <head> <meta charset="UTF-8"> ...... </head> <body> ...... </body> </html> ` #### [建议] HTML 文件使用无 BOMUTF-8 编码。 解释: UTF-8 编码具有更广泛的适应性。BOM 在使用程序或工具处理文件时可能造成不必要的干扰。 ### CSS 和 JavaScript 引入 #### [强制] 引入 CSS 时必须指明 rel="stylesheet"。 示例: `(html) <link rel="stylesheet" href="page.css"> ` #### [建议] 引入 CSSJavaScript 时无须指明 type 属性。 解释: text/csstext/javascripttype 的默认值。 #### [建议] 在 head 中引入页面需要的所有 CSS 资源。 解释: 在页面渲染的过程中,新的CSS可能导致元素的样式重新计算和绘制,页面闪烁。 #### [建议] JavaScript 应当放在页面末尾,或采用异步加载。 解释: 将 script 放在页面中间将阻断页面的渲染。出于性能方面的考虑,如非必要,请遵守此条建议。 示例: `(html) <body> <!-- a lot of elements --> <script src="init-behavior.js"></script> </body> ` ## head ### title #### [强制] 页面必须包含 title 标签声明标题。 #### [强制] title 必须作为 head 的直接子元素,并紧随 charset 声明之后。 解释: title 中如果包含 ASCII 之外的字符,浏览器需要知道字符编码类型才能进行解码,否则可能导致乱码。 示例: `(html) <head> <meta charset="UTF-8"> <title>页面标题</title> </head> ` ### favicon #### [强制] 保证 favicon 可访问。 解释: 在未指定 favicon 时,大多数浏览器会请求 Web Server 根目录下的 favicon.ico 。为了保证 favicon 可访问,避免 404,必须遵循以下两种方法之一: 1. 在 Web Server 根目录放置 favicon.ico 文件。 2. 使用 link 指定 favicon。 示例: `(html) <link rel="shortcut icon" href="path/to/favicon.ico"> ` ### viewport #### [建议] 若页面欲对移动设备友好,需指定页面的 viewport。 解释: viewport meta tag 可以设置可视区域的宽度和初始缩放大小,避免在移动设备上出现页面展示不正常。 比如,在页面宽度小于 980px 时,若需 iOS 设备友好,应当设置 viewport 的 width 值来适应你的页面宽度。同时因为不同移动设备分辨率不同,在设置时,应当使用 device-widthdevice-height 变量。 另外,为了使 viewport 正常工作,在页面内容样式布局设计上也要做相应调整,如避免绝对定位等。关于 viewport 的更多介绍,可以参见 Safari Web Content Guide的介绍 ## 图片 #### [强制] 禁止 imgsrc 取值为空。延迟加载的图片也要增加默认的 src。 解释: src 取值为空,会导致部分浏览器重新加载一次当前页面,参考:https://developer.yahoo.com/p... #### [建议] 避免为 img 添加不必要的 title 属性。 解释: 多余的 title 影响看图体验,并且增加了页面尺寸。 #### [建议] 为重要图片添加 alt 属性。 解释: 可以提高图片加载失败时的用户体验。 #### [建议] 添加 widthheight 属性,以避免页面抖动。 #### [建议] 有下载需求的图片采用 img 标签实现,无下载需求的图片采用 CSS 背景图实现。 解释: 1. 产品 logo、用户头像、用户产生的图片等有潜在下载需求的图片,以 img 形式实现,能方便用户下载。 2. 无下载需求的图片,比如:icon、背景、代码使用的图片等,尽可能采用 CSS 背景图实现。 ## 表单 ### 控件标题 #### [强制] 有文本标题的控件必须使用 label 标签将其与其标题相关联。 解释: 有两种方式: 1. 将控件置于 label 内。 2. labelfor 属性指向控件的 id。 推荐使用第一种,减少不必要的 id。如果 DOM 结构不允许直接嵌套,则应使用第二种。 示例: `(html) <label><input type="checkbox" name="confirm" value="on"> 我已确认上述条款</label> <label for="username">用户名:</label> <input type="textbox" name="username" id="username"> ` ### 按钮 #### [强制] 使用 button 元素时必须指明 type 属性值。 解释: button 元素的默认 typesubmit,如果被置于 form 元素中,点击后将导致表单提交。为显示区分其作用方便理解,必须给出 type 属性。 示例: `(html) <button type="submit">提交</button> <button type="button">取消</button> ` #### [建议] 尽量不要使用按钮类元素的 name 属性。 解释: 由于浏览器兼容性问题,使用按钮的 name 属性会带来许多难以发现的问题。具体情况可参考此文。 ### 可访问性 #### [建议] 在针对移动设备开发的页面时,根据内容类型指定输入框的 type 属性。 解释: 根据内容类型指定输入框类型,能获得能友好的输入体验。 示例: `(html) <input type="date"> ` ## 多媒体 #### [建议] 当在现代浏览器中使用 audio 以及 video 标签来播放音频、视频时,应当注意格式。 解释: 音频应尽可能覆盖到如下格式: * MP3 * WAV * Ogg 视频应尽可能覆盖到如下格式: * MP4 * WebM * Ogg #### [建议] 在支持 HTML5 的浏览器中优先使用 audiovideo 标签来定义音视频元素。 #### [建议] 只在必要的时候开启音视频的自动播放。 ## 2.2.css编码规范 CSS 作为网页样式的描述语言,在百度一直有着广泛的应用。本文档的目标是使 CSS 代码风格保持一致,容易被理解和被维护。 虽然本文档是针对 CSS 设计的,但是在使用各种 CSS 的预编译器(如 less、sass、stylus 等)时,适用的部分也应尽量遵循本文档的约定。 ## 代码风格 ### 文件 #### [建议] CSS 文件使用无 BOMUTF-8 编码。 解释: UTF-8 编码具有更广泛的适应性。BOM 在使用程序或工具处理文件时可能造成不必要的干扰。 ### 缩进 #### [强制] 使用 4 个空格做为一个缩进层级,不允许使用 2 个空格 或 tab 字符。 示例: `css .selector { margin: 0; padding: 0; } ` ### 空格 #### [强制] 选择器{ 之间必须包含空格。 示例: `css .selector { } ` #### [强制] 属性名 与之后的 : 之间不允许包含空格, :属性值 之间必须包含空格。 示例: `css margin: 0; ` #### [强制] 列表型属性值 书写在单行时,, 后必须跟一个空格。 示例: `css font-family: Arial, sans-serif; ` ### 行长度 #### [强制] 每行不得超过 120 个字符,除非单行不可分割。 解释: 常见不可分割的场景为URL超长。 #### [建议] 对于超长的样式,在样式值的 空格 处或 , 后换行,建议按逻辑分组。 示例: `css / 不同属性值按逻辑分组 / background: transparent url(aVeryVeryVeryLongUrlIsPlacedHere) no-repeat 0 0; / 可重复多次的属性,每次重复一行 / background-image: url(aVeryVeryVeryLongUrlIsPlacedHere) url(anotherVeryVeryVeryLongUrlIsPlacedHere); / 类似函数的属性值可以根据函数调用的缩进进行 / background-image: -webkit-gradient( linear, left bottom, left top, color-stop(0.04, rgb(88,94,124)), color-stop(0.52, rgb(115,123,162)) ); ` ### 选择器 #### [强制] 当一个 rule 包含多个 selector 时,每个选择器声明必须独占一行。 示例: `css / good / .post, .page, .comment { line-height: 1.5; } / bad / .post, .page, .comment { line-height: 1.5; } ` #### [强制] >+~ 选择器的两边各保留一个空格。 示例: `css / good / main > nav { padding: 10px; } label + input { margin-left: 5px; } input:checked ~ button { background-color: #69C; } / bad / main>nav { padding: 10px; } label+input { margin-left: 5px; } input:checked~button { background-color: #69C; } ` #### [强制] 属性选择器中的值必须用双引号包围。 解释: 不允许使用单引号,不允许不使用引号。 示例: `css / good / article[character="juliet"] { voice-family: "Vivien Leigh", victoria, female; } / bad / article[character='juliet'] { voice-family: "Vivien Leigh", victoria, female; } ` ### 属性 #### [强制] 属性定义必须另起一行。 示例: `css / good / .selector { margin: 0; padding: 0; } / bad / .selector { margin: 0; padding: 0; } ` #### [强制] 属性定义后必须以分号结尾。 示例: `css / good / .selector { margin: 0; } / bad / .selector { margin: 0 } ` ## 通用 ### 选择器 #### [强制] 如无必要,不得为 idclass 选择器添加类型选择器进行限定。 解释: 在性能和维护性上,都有一定的影响。 示例: `css / good / #error, .danger-message { font-color: #c00; } / bad / dialog#error, p.danger-message { font-color: #c00; } ` #### [建议] 选择器的嵌套层级应不大于 3 级,位置靠后的限定条件应尽可能精确。 示例: `css / good / #username input {} .comment .avatar {} / bad / .page .header .login #username input {} .comment div * {} ` ### 属性缩写 #### [建议] 在可以使用缩写的情况下,尽量使用属性缩写。 示例: `css / good / .post { font: 12px/1.5 arial, sans-serif; } / bad / .post { font-family: arial, sans-serif; font-size: 12px; line-height: 1.5; } ` #### [建议] 使用 border / margin / padding 等缩写时,应注意隐含值对实际数值的影响,确实需要设置多个方向的值时才使用缩写。 解释: border / margin / padding 等缩写会同时设置多个属性的值,容易覆盖不需要覆盖的设定。如某些方向需要继承其他声明的值,则应该分开设置。 示例: `css / centering <article class="page"> horizontally and highlight featured ones / article { margin: 5px; border: 1px solid #999; } / good / .page { margin-right: auto; margin-left: auto; } .featured { border-color: #69c; } / bad / .page { margin: 5px auto; / introducing redundancy / } .featured { border: 1px solid #69c; / introducing redundancy / } ` ### 属性书写顺序 #### [建议] 同一 rule set 下的属性在书写时,应按功能进行分组,并以 Formatting Model(布局方式、位置) > Box Model(尺寸) > Typographic(文本相关) > Visual(视觉效果) 的顺序书写,以提高代码的可读性。 解释: - Formatting Model 相关属性包括:position / top / right / bottom / left / float / display / overflow 等 - Box Model 相关属性包括:border / margin / padding / width / height 等 - Typographic 相关属性包括:font / line-height / text-align / word-wrap 等 - Visual 相关属性包括:background / color / transition / list-style 等 另外,如果包含 content 属性,应放在最前面。 示例: `css .sidebar { / formatting model: positioning schemes / offsets / z-indexes / display / ... / position: absolute; top: 50px; left: 0; overflow-x: hidden; / box model: sizes / margins / paddings / borders / ... / width: 200px; padding: 5px; border: 1px solid #ddd; / typographic: font / aligns / text styles / ... / font-size: 14px; line-height: 20px; / visual: colors / shadows / gradients / ... / background: #f5f5f5; color: #333; -webkit-transition: color 1s; -moz-transition: color 1s; transition: color 1s; } ` ### 清除浮动 ### !important #### [建议] 尽量不使用 !important 声明。 #### [建议] 当需要强制指定样式且不允许任何场景覆盖时,通过标签内联和 !important 定义样式。 解释: 必须注意的是,仅在设计上 确实不允许任何其它场景覆盖样式 时,才使用内联的 !important 样式。通常在第三方环境的应用中使用这种方案。下面的 z-index 章节是其中一个特殊场景的典型样例。 ## 值与单位 ### 文本 #### [强制] 文本内容必须用双引号包围。 解释: 文本类型的内容可能在选择器、属性值等内容中。 示例: `css / good / html[lang|="zh"] q:before { font-family: "Microsoft YaHei", sans-serif; content: "“"; } html[lang|="zh"] q:after { font-family: "Microsoft YaHei", sans-serif; content: "”"; } / bad / html[lang|=zh] q:before { font-family: 'Microsoft YaHei', sans-serif; content: '“'; } html[lang|=zh] q:after { font-family: "Microsoft YaHei", sans-serif; content: "”"; } ` ### url() #### [强制] url() 函数中的路径不加引号。 示例: `css body { background: url(bg.png); } ` #### [建议] url() 函数中的绝对路径可省去协议名。 示例: `css body { background: url(//baidu.com/img/bg.png) no-repeat 0 0; } ` ### 颜色 #### [强制] RGB颜色值必须使用十六进制记号形式 #rrggbb。不允许使用 rgb()。 解释: 带有alpha的颜色信息可以使用 rgba()。使用 rgba() 时每个逗号后必须保留一个空格。 示例: `css / good / .success { box-shadow: 0 0 2px rgba(0, 128, 0, .3); border-color: #008000; } / bad / .success { box-shadow: 0 0 2px rgba(0,128,0,.3); border-color: rgb(0, 128, 0); } ` #### [强制] 颜色值可以缩写时,必须使用缩写形式。 示例: `css / good / .success { background-color: #aca; } / bad / .success { background-color: #aaccaa; } ` #### [强制] 颜色值不允许使用命名色值。 示例: `css / good / .success { color: #90ee90; } / bad / .success { color: lightgreen; } ` #### [建议] 颜色值中的英文字符采用小写。如不用小写也需要保证同一项目内保持大小写一致。 示例: `css / good / .success { background-color: #aca; color: #90ee90; } / good / .success { background-color: #ACA; color: #90EE90; } / bad / .success { background-color: #ACA; color: #90ee90; } ` ### 字体族 字体解决方案参考 #### [强制] font-family 按「西文字体在前、中文字体在后」、「效果佳 (质量高/更能满足需求) 的字体在前、效果一般的字体在后」的顺序编写,最后必须指定一个通用字体族( serif / sans-serif )。 解释: 更详细说明可参考本文。 示例: `css / Display according to platform / .article { font-family: Arial, sans-serif; } / Specific for most platforms / h1 { font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", sans-serif; } ` #### [强制] font-family 不区分大小写,但在同一个项目中,同样的 Family Name 大小写必须统一。 示例: `css / good / body { font-family: Arial, sans-serif; } h1 { font-family: Arial, "Microsoft YaHei", sans-serif; } / bad / body { font-family: arial, sans-serif; } h1 { font-family: Arial, "Microsoft YaHei", sans-serif; } ` ### 字号 #### [强制] 需要在 Windows 平台显示的中文内容,其字号应不小于 12px。 解释: 由于 Windows 的字体渲染机制,小于 12px 的文字显示效果极差、难以辨认。 ### 字体风格 #### [建议] 需要在 Windows 平台显示的中文内容,不要使用除 normal 外的 font-style。其他平台也应慎用。 解释: 由于中文字体没有 italic 风格的实现,所有浏览器下都会 fallback 到 obilique 实现 (自动拟合为斜体),小字号下 (特别是 Windows 下会在小字号下使用点阵字体的情况下) 显示效果差,造成阅读困难。 ### 字重 #### [强制] font-weight 属性必须使用数值方式描述。 解释: CSS 的字重分 100 – 900 共九档,但目前受字体本身质量和浏览器的限制,实际上支持 400700 两档,分别等价于关键词 normalbold。 浏览器本身使用一系列启发式规则来进行匹配,在 <700 时一般匹配字体的 Regular 字重,>=700 时匹配 Bold 字重。 但已有浏览器开始支持 =600 时匹配 Semibold 字重 (见此表),故使用数值描述增加了灵活性,也更简短。 示例: `css / good / h1 { font-weight: 700; } / bad / h1 { font-weight: bold; } ` ### 行高 #### [建议] line-height 在定义文本段落时,应使用数值。 解释: 将 line-height 设置为数值,浏览器会基于当前元素设置的 font-size 进行再次计算。在不同字号的文本段落组合中,能达到较为舒适的行间间隔效果,避免在每个设置了 font-size 都需要设置 line-height。 当 line-height 用于控制垂直居中时,还是应该设置成与容器高度一致。 示例: `css .container { line-height: 1.5; } ` ## 变换与动画 #### [强制] 使用 transition 时应指定 transition-property。 示例: `css / good / .box { transition: color 1s, border-color 1s; } / bad / .box { transition: all 1s; } ` #### [建议] 尽可能在浏览器能高效实现的属性上添加过渡和动画。 解释: 见本文,在可能的情况下应选择这样四种变换: * transform: translate(npx, npx); * transform: scale(n); * transform: rotate(ndeg); * opacity: 0..1; 典型的,可以使用 translate 来代替 left 作为动画属性。 示例: `css / good / .box { transition: transform 1s; } .box:hover { transform: translate(20px); / move right for 20px / } / bad / .box { left: 0; transition: left 1s; } .box:hover { left: 20px; / move right for 20px / } `

要么努力,要么放
1 声望0 粉丝