开发灵活,稳定,可维护的 HTML, CSS 和 JavaScript 代码的规范。
编码规范的好处:不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。
项目命名(Naming Project)
项目名
项目名全部采用小写方式, 以中划线分隔。 比如: my-project-name
目录名
目录名参照上一条规则,有复数结构时,要采用复数命名法,比如说: scripts, styles, images, data-models
JS文件命名
所有js文件名,多个单词组成时,采用中划线连接方式,比如说: 账号模型文件 account-model.js
CSS&&CSS文件命名
多个单词组成时,采用中划线连接方式,比如说:retina-sprites.scss
HTML文件命名
多个单词组成时,采用中划线连接方式,比如说: error-report.html
HTML
语法
- 使用四个空格的 soft tabs — 这是保证代码在各种环境下显示一致的唯一方式。
嵌套的节点应该缩进(四个空格)。 - 在属性上,使用双引号,不要使用单引号。
- 不要在自动闭合标签结尾处使用斜线 - HTML5 规范 指出他们是可选的。
如:<img src=“xx.jpg” alt=“xx”>
HTML5 doctype
在每个 HTML 页面开头使用这个简单地 doctype 来启用标准模式,使其每个浏览器中尽可能一致的展现。
虽然doctype不区分大小写,但是按照惯例,doctype大写。
<!DOCTYPE html>
语言属性
根据 HTML5 规范:
强烈建议为 html 根元素指定 lang 属性,从而为文档设置正确的语言。这将有助于语音合成工具确定其所应该采用的发音,有助于翻译工具确定其翻译时所应遵守的规则等等。
考虑到兼容性,目前需要指定中文的网页都统一用 zh-CN
IE兼容模式(IE compatibility mode)
IE 支持通过特定的 标签来确定绘制当前页面所应该采用的 IE 版本。除非有强烈的特殊需求,否则最好是设置为 edge mode,从而通知 IE 采用其所支持的最新的模式。
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
字符编码
通过声明一个明确的字符编码,让浏览器轻松、快速的确定适合网页内容的渲染方式。
<head>
<meta charset="UTF-8">
</head>
引入CSS和JavaScript
根据 HTML5 规范, 通常在引入 CSS 和 JavaScript 时不需要指明 type,因为 text/css 和 text/javascript 分别是他们的默认值。
实用高于完美
尽量遵循 HTML 标准和语义,但是不应该以浪费实用性作为代价。任何时候都要用尽量小的复杂度和尽量少的标签来解决问题。
属性顺序
HTML 属性应该按照特定的顺序出现以保证易读性。
- class
- id
- name
- data-*
- src, for, type, href, value , max-length, max, min, pattern
- placeholder, title, alt
- aria-*, role
- required, readonly, disabled
Class 是为高可复用组件设计的,理论上他们应处在第一位。Id更加具体而且应该尽量少使用(例如, 页内书签),所以他们处在第二位。
Boolean 属性
Boolean 属性指不需要声明取值的属性。XHTML 需要每个属性声明取值,但是 HTML5 并不需要。
减少标签数量
在编写 HTML 代码时,需要尽量避免多余的父节点。很多时候,需要通过迭代和重构来使 HTML 变得更少。
Javascript生成标签
在 JavaScript 文件中生成标签让内容变得更难查找,更难编辑,性能更差。应该尽量避免这种情况的出现。
CSS
CSS 语法
- 使用四个空格的 soft tabs — 这是保证代码在各种环境下显示一致的唯一方式。
- 使用组合选择器时,保持每个独立的选择器占用一行。
- 为了代码的易读性,在每个声明的左括号前增加一个空格。
- 声明块的右括号应该另起一行。
- 每条声明 : 后应该插入一个空格。
- 每条声明应该只占用一行来保证错误报告更加准确。
- 所有声明应该以分号结尾。虽然最后一条声明后的分号是可选的,但是如果没有他,你的代码会更容易出错。
- 逗号分隔的取值,都应该在逗号之后增加一个空格。比如说box-shadow
- 不要在颜色值 rgb() rgba() hsl() hsla()和 rect() 中增加空格,并且不要带有取值前面不必要的 0 (比如,使用 .5 替代 0.5)。This helps differentiate multiple color values (comma, no space) from multiple property values (comma with space).
- 所有的十六进制值都应该使用小写字母,例如 #fff。因为小写字母有更多样的外形,在浏览文档时,他们能够更轻松的被区分开来。
- 尽可能使用短的十六进制数值,例如使用 #fff 替代 #ffffff。
- 为选择器中的属性取值添加引号,例如 input[type=“text”]。 他们只在某些情况下可有可无,所以都使用引号可以增加一致性。
- 不要为 0 指明单位,比如使用 margin: 0; 而不是 margin: 0px;。
声明顺序
相关的属性声明应该以下面的顺序分组处理:
Positioning
Box model 盒模型
Typographic 排版
Visual 外观
Positioning 处在第一位,因为他可以使一个元素脱离正常文本流,并且覆盖盒模型相关的样式。盒模型紧跟其后,因为他决定了一个组件的大小和位置。
其他属性只在组件 内部 起作用或者不会对前面两种情况的结果产生影响,所以他们排在后面。
如:
.declaration-order {
/* Positioning */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
/* Box-model */
display: block;
float: right;
width: 100px;
height: 100px;
/* Typography */
font: normal 13px "Helvetica Neue", sans-serif;
line-height: 1.5;
color: #333;
text-align: center;
/* Visual */
background-color: #f5f5f5;
border: 1px solid #e5e5e5;
border-radius: 3px;
/* Misc */
opacity: 1;
}
不要用 @import
与 标签相比,@import 指令要慢很多,不光增加了额外的请求次数,还会导致不可预料的问题。替代办法有以下几种:
- 使用多个 元素
- 通过 Sass 或 Less 类似的 CSS 预处理器将多个 CSS 文件编译为一个文件
- 通过 Rails、Jekyll 或其他系统中提供过 CSS 文件合并功能
媒体查询位置
尽量将媒体查询的位置靠近他们相关的规则。不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部。这样做只会让大家以后更容易忘记他们。这里是一个典型的案例。
.element { ... }
.element-avatar { ... }
.element-selected { ... }
@media (min-width: 480px) {
.element { ...}
.element-avatar { ... }
.element-selected { ... }
}
单条声明的声明块
在一个声明块中只包含一条声明的情况下,为了易读性和快速编辑可以考虑移除其中的换行。所有包含多条声明的声明块应该分为多行。
这样做的关键因素是错误检测 - 例如,一个 CSS 验证程序显示你在 183 行有一个语法错误,如果是一个单条声明的行,那就是他了。在多个声明的情况下,你必须为哪里出错了费下脑子。
/* Single declarations on one line */
.span1 { width: 60px; }
.span2 { width: 140px; }
.span3 { width: 220px; }
/* Multiple declarations, one per line */
.sprite {
display: inline-block;
width: 16px;
height: 15px;
background-image: url(../img/sprite.png);
}
属性简写
坚持限制属性取值简写的使用,属性简写需要你必须显式设置所有取值。常见的属性简写滥用包括:
- padding
- margin
- font
- background
- border
- border-radius
大多数情况下,我们并不需要设置属性简写中包含的所有值。例如,HTML 头部只设置上下的 margin,所以如果需要,只设置这两个值。过度使用属性简写往往会导致更混乱的代码,其中包含不必要的重写和意想不到的副作用。
/* Bad example */
.element {
margin: 0 0 10px;
background: red;
background: url("image.jpg");
border-radius: 3px 3px 0 0;
}
/* Good example */
.element {
margin-bottom: 10px;
background-color: red;
background-image: url("image.jpg");
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
Less 和 Sass 中的嵌套
避免不必要的嵌套。可以进行嵌套,不意味着你应该这样做。只有在需要给父元素增加样式并且同时存在多个子元素时才需要考虑嵌套。
代码注释
代码是由人来编写和维护的。保证你的代码是描述性的,包含好的注释,并且容易被他人理解。好的代码注释传达上下文和目标。不要简单地重申组件或者 class 名称。
Class 命名
- 保持 Class 命名为全小写,可以使用短划线(不要使用下划线和 camelCase 命名)。短划线应该作为相关类的自然间断。(例如,.btn 和 .btn-danger)。
- 避免过度使用简写。.btn 可以很好地描述 button,但是 .s 不能代表任何元素。
- Class 的命名应该尽量短,也要尽量明确。
- 使用有意义的名称;使用结构化或者作用目标相关,而不是抽象的名称。
- 命名时使用最近的父节点或者父 class 作为前缀。
- 使用 .js-* classes 来表示行为(相对于样式),但是不要在 CSS 中包含这些 classes。
选择器
- 使用 classes 而不是通用元素标签来优化渲染性能。
- 避免在经常出现的组件中使用一些属性选择器 (例如,[class^="…"])。浏览器性能会受到这些情况的影响。
- 减少选择器的长度,每个组合选择器选择器的条目应该尽量控制在 3 个以内。
代码组织
- 以组件为单位组织代码。
- 制定一个一致的注释层级结构。
- 使用一致的空白来分割代码块,这样做在查看大的文档时更有优势。
JavaScript
Indentation,分号,单行长度
- 一律使用4个空格
- Statement 之后一律以分号结束, 不可以省略
- 单行长度,理论上不要超过80列,不过如果编辑器开启 soft wrap 的话可以不考虑单行长度
空行
- 方法之间加
- 单行或多行注释前加
- 逻辑块之间加空行增加可读性
变量命名
- 标准变量采用驼峰标识
- 使用的ID的地方一定全大写
- 使用的URL的地方一定全大写, 比如说 reportURL
- 涉及Android的,一律大写第一个字母
- 涉及iOS的,一律小写第一个,大写后两个字母
- 常量采用大写字母,下划线连接的方式
- 构造函数,大写第一个字母
字符常量
一般情况下统一使用 ‘’ 单引号
null使用场景
- 初始化一个变量,该变量稍后可能被分配一个对象值。
undefined使用场景
- 永远不要直接使用undefined进行变量判断
- 使用字符串 “undefined” 对变量进行判断
Object 字面量
// Bad
var team = new Team();
team.title = "AlloyTeam";
team.count = 25;
// Good
var team = {
title: "AlloyTeam",
count: 25
};
Array 字面量
// Bad
var colors = new Array("red", "green", "blue");
var numbers = new Array(1, 2, 3, 4);
// Good
var colors = [ "red", "green", "blue" ];
var numbers = [ 1, 2, 3, 4 ];
单行注释
- 双斜线后,必须跟注释内容保留一个空格
- 可独占一行, 缩进与下一行代码保持一致
- 可位于一个代码行的末尾,注意这里的格式(双斜线距离分号四个空格,双斜线后始终保留一个空格)
如:
var zhangsan = "zhangsan"; // 双斜线距离分号四个空格,双斜线后始终保留一个空格
多行注释
- 最少三行
- 前边留空一行
/*
* 注释内容与星标前保留一个空格
*/
多行注释使用场景
- 难于理解的代码段
- 可能存在错误的代码段
- 浏览器特殊的HACK代码
- 想吐槽的产品逻辑, 合作同事
- 业务逻辑强相关的代码
文档注释
参考 这里
括号对齐
- 标准示例 括号前后有空格, 花括号起始 不另换行,结尾新起一行
- 花括号必须要, 即使内容只有一行
- 涉及 if 、for 、while、 do…while、 try…catch…finally 的地方都必须使用花括号
// Good
if (condition) {
doSomething();
}
if else
if else else前后留有空格
if (condition) {
doSomething();
} else {
doSomethingElse();
}
switch
- switch和括号之间有空格, case需要缩进, break之后跟下一个case中间留一个blank line
- 花括号必须要, 即使内容只有一行。
- switch 的 falling through 一定要有注释特别说明, no default 的情况也需要注释特别说明况
switch (condition) {
// obvious fall through // 这里为啥JSHint默认就会放过,因为 case "first" 内无内容
case "first":
case "second":
// code
break;
case "third":
// code
/* falls through */ // 这里为啥要加这样的注释, 明确告知JSHint放过此处告警
default:
// code
}
for
- 普通for循环, 分号后留有一个空格, 判断条件等内的操作符两边不留空格, 前置条件如果有多个,逗号后留一个空格
- for-in 一定要有 hasOwnProperty 的判断, 否则 JSLint 或者 JSHint 都会有一个 warn
var values = [ 1, 2, 3, 4, 5, 6, 7 ],
i, len;
for (i=0, len=values.length; i<len; i++) {
process(values[i]);
}
var prop;
for (prop in object) {
// 注意这里一定要有 hasOwnProperty 的判断, 否则 JSLint 或者 JSHint 都会有一个 warn !
if (object.hasOwnProperty(prop)) {
console.log("Property name is " + prop);
console.log("Property value is " + object[prop]);
}
}
变量声明
所有函数内变量声明放在函数内头部,只使用一个 var(多了JSLint报错), 一个变量一行, 在行末跟注释,
function doSomethingWithItems(items) {
var value = 10, // 注释啊
result = value + 10, // 注释啊
i, // 注释啊
len; // 注释啊
for (i=0, len=items.length; i < len; i++) {
doSomething(items[i]);
}
}
函数声明
- 一定先声明再使用
- 函数声明 有函数名的时候不需要空格, 没有函数名的时候需要空格。
- 立即执行函数的写法, 最外层必须包一层括号
- “use strict” 决不允许全局使用, 必须放在函数的第一行, 可以用自执行函数包含大的代码段, 如果 “use strict” 在函数外使用, JSLint 和 JSHint 均会报错
function doSomething(item) {
// do something
}
var doSomething = function (item) {
// do something
}
// Good
doSomething(item);
// Good
var value = (function() {
// function body
return {
message: "Hi"
}
}());
// Good
(function() {
"use strict";
function doSomething() {
// code
}
function doSomethingElse() {
// code
}
})();
杂项
- 完全避免 == != 的使用, 用严格比较条件 === !==
- eval 非特殊业务, 禁用!!!
- with 非特殊业务, 禁用!!!