HTML和CSS编码规范

写个人项目是最爽的,再稀烂的代码都是自己的孩子,一把屎一把尿写出来的,总能认得。但是阅读本文的你,多半是给别人写码,面向老板编程的。你的码保不齐日后要别人维护。为了写出放心的码,提高搬砖效率,统一编码规范是必然的选择。

Boss Oriented Programming

有观众可能要问了,我们不是有lint工具吗?

就你话多

HTML

基本

doctype

每个页面开头,使用简单的<!DOCTYPE html>来启用标准模式。

1
2
3
4
5
<!-- bad -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!-- good -->
<!DOCTYPE html>

charset

无特殊情况时,统一使用UTF-8

lang

推荐在html元素上使用lang属性

viewport

建议指定页面的viewport属性,保证移动端的友好展示

1
<meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=1, user-scalable=no">

title

head必须要有title标签。

IE兼容模式

如不是特殊需要,通过edge mode通知IE使用最新的兼容模式。

1
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">

CSS和JavaScript引入

  • 引入CSS和JavaScript时不需要指明type,因为text/csstext/javascript分别是他们的默认值。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- bad -->
    <!DOCTYPE html>
    <head>
    <link type="text/css" rel="stylesheet" href="index.css">
    <script type="text/javascript" src="index.js"></script>
    </head>

    <!-- good -->
    <!DOCTYPE html>
    <head>
    <link rel="stylesheet" href="index.css">
    <script src="index.js"></script>
    </head>
  • CSS在<head></head>中引入,基础JS脚本在<head></head>引入,其余在<body>结束标签前引入

缩进

必须使用两个空格表示一个缩进层级,禁止使用tab

1
2
3
4
5
6
7
8
9
<!-- bad -->
<div>
<p>just a example</p>
</div>

<!-- good -->
<div>
<p>just a example</p>
</div>

换行

单行不能超过120个字符

标签名称和标签属性统一使用小写

1
2
3
4
5
<!-- bad -->
<Div Id="foo"></Div>

<!-- good -->
<div id="foo"></div>

综上,下面是一个建议的html脚手架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=1, user-scalable=no">
<meta name="renderer" content="webkit">
<meta name="author" content="shenlvmeng">
<meta name="description" content="描述">
<meta name="keyword" content="关键词">
<title>Foo</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<script src="index.js"></script>
</body>
</html>

标签

  • 非自闭合标签必须有开始和结束标签,自动闭合标签不建议在结尾处使用斜线/
    1
    2
    3
    4
    5
    6
    <!-- bad -->
    <div class="foo" />
    <img src="foo.png" />
    <!-- good -->
    <div class="foo"></div>
    <img src="foo.png">
  • 建议使用语义化标签
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- good -->
    <header></header>
    <section>
    <nav>Navbar</nav>
    <article>
    <time>2017</time>
    <figure></figure>
    </article>
    <aside></aside>
    </section>
    <footer></footer>
  • 避免标签嵌套层级过深,尤其是无语义的嵌套
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!-- bad -->
    <div class="foo">
    <div class="bar">
    <div class="container">
    <div class="content">
    </div>
    </div>
    </div>
    </div>

命名

标签名

必须使用小写字母加连字符的命名方式

1
2
3
4
<!-- bad -->
<MyTag></MyTag>
<!-- good -->
<my-tag></my-tag>

class属性

使用小写字母加连字符,需要在Javascript中使用时,以J_开头,接大驼峰命名

1
2
3
4
<!-- bad -->
<div class="FooBar J_foo-bar"></div>
<!-- good -->
<div class="foo-bar J_FooBar"></div>

id属性

同上。建议使用class属性关联CSS。

属性

使用双引号包裹

1
2
3
4
<!-- bad -->
<div class='foo'></div>
<!-- good -->
<div class="foo"></div>

Boolean属性

不要为Boolean属性指定值。

一个元素中 Boolean 属性的存在表示取值true,不存在则表示取值false。

1
2
3
4
5
6
7
8
9
10
11
12
<!-- bad -->
<input type="text" name="nickname" disabled="disabled">
<input type="checkbox" name="hobbies" value="bicycle" checked="checked">
<select>
<option value="FrontEnd" selected="selected">FrontEnd</option>
</select>
<!-- good -->
<input type="text" name="nickname" disabled>
<input type="checkbox" name="hobbies" value="bicycle" checked>
<select>
<option value="FrontEnd" selected>FrontEnd</option>
</select>

自定义属性

必须data-为前缀,保证可读

1
2
3
4
<!-- bad -->
<div age="10"></div>
<!-- good -->
<div data-age="10"></div>

顺序

保证可读性,一致的属性顺序可以提高压缩率。按照出现频率,依次是:

  • class
  • id
  • data-*

少用style属性

建议使用class来控制样式,可以提高可维护性和可读性。

不在属性值中使用JavaScript语句

1
2
3
4
5
6
7
8
<!-- bad -->
<a id="hello" href="javascript:alert('hi');" onclick=";(function(){alert('hello');})()">
<!-- good -->
<script>
document.getElementById("hello").addEventListener(function() {
alert('hello');
});
</script>

多媒体

  • imgsrc属性禁止留空
  • img标签添加alt属性以声明替代文本
  • 在多媒体标签内部提供指示浏览器不支持该标签的说明,如objectaudiovideo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- bad -->
<img src="cat.png">
<audio controls>
<source src="foo.ogg" type="audio/ogg">
<source src="bar.mp3" type="audio/mpeg">
</audio>

<!-- good -->
<img src="cat.png" alt="cat">
<audio controls>
<source src="baz.ogg" type="audio/ogg">
<source src="qaz.mp3" type="audio/mpeg">
Your browser does not support the audio tag.
</audio>

CSS

基本

  • 推荐使用两个空格缩进
    1
    2
    3
    4
    5
    6
    7
    8
    /* bad */
    .example {
    color: #fff;
    }
    /* good */
    .example {
    color: #000;
    }
  • 单行不能超过120个字符,除非不可分割,如URL
  • 声明块左花括号前推荐添加空格
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* bad */
    .example{
    width: 100px;
    }

    /* good */
    .example {
    height: 15px;
    }
  • 声明块右花括号推荐单独成行
    1
    2
    3
    4
    5
    6
    7
    8
    /* bad */
    .example {
    width: 100px;}

    /* good */
    .example {
    height: 15px;
    }
  • 声明语句:需要有空格,前无空格
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* bad */
    .example {
    left:15px;
    }

    /* good */
    .example {
    top: 15px;
    }
  • 声明语句必须以分号结尾
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* bad */
    .example {
    left:15px
    }

    /* good */
    .example {
    top: 15px;
    }

注释

文档注释

声明在文件头部,表示文件作用

1
2
3
/**
* 这个文件的作用
*/

代码注释

传达代码上下文和目标,应该容易被人类理解。不要简单重复类名等冗余信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* bad */

/* header */
.header {
text-align: center;
...
}

/* good */

/* Wrapping contents of .title and .user-info */
.header {
text-align: center;
...
}

命名

同HTML规范,小写字母加短划线-。在JavaScript中出现的类名用J_开头,后接大驼峰命名,这类的class不能出现在CSS文件中。

  • 文本内容必须使用双引号包裹
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /* bad */
    html[lang|=zh] q:before {
    font-family: 'Microsoft YaHei', sans-serif;
    content: '“';
    }
    /* good */
    html[lang|="zh"] q:before {
    font-family: "Microsoft YaHei", sans-serif;
    content: "“";
    }
  • “0”值后不要使用单位。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* bad */
    .example {
    margin: 0px;
    }

    /* good */
    .example {
    margin: 0;
    }
  • 长度数值是0 - 1间的小数时,忽略整数部分的0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* bad */
    panel {
    opacity: 0.8
    }

    /* good */
    panel {
    opacity: .8
    }
  • 颜色值必须使用小写的十六进制表示,禁止使用颜色名和rgb(),带有透明度时可以使用rgba()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /* bad */
    .success {
    box-shadow: 0 0 2px rgba(0,128,0,.3);
    border-color: rgb(0, 128, 0);
    }

    /* good */
    .success {
    box-shadow: 0 0 2px rgba(0, 128, 0, .3);
    border-color: #008000;
    }
  • 可以缩写时,颜色值必须缩写
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* bad */
    .success {
    background-color: #aaccaa;
    }

    /* good */
    .success {
    background-color: #aca;
    }
  • url()函数中的路径禁止带引号,绝对路径时可以省去协议名
    1
    2
    3
    .logo {
    background: url(//assets/logo.png);
    }

选择器

  • 一个rule包含多个选择器时,每个选择器必须独占一行
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /* bad */
    .post, .page, .comment {
    line-height: 1.5;
    }

    /* good */
    .post,
    .page,
    .comment {
    line-height: 1.5;
    }
  • 属性选择器中的值必须用双引号包裹
    1
    2
    3
    p[lang|="zh"] {
    font-size: 12px;
    }
  • 选择器层级不要超过5级,靠后的选择器尽量精确
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* bad */
    .main .top .left .mod-a .content .detail {
    padding-left: 15px;
    }

    /* good */
    .content .detail {
    padding-left: 15px;
    }

属性

  • 建议相关的属性说明放在一组,并按下面顺序排列
    1. 定位(position、left、right、top、bottom、z-index)
    2. 盒子模型(display、float、width、height、margin、padding、border、border-radius)
    3. 排印(font、color、background、line-height、text-align)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      .mod-example {
      /* 定位 */
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 100;
      /* 盒模型 */
      display: block;
      float: right;
      width: 100px;
      height: 100px;
      margin: 15px auto;
      padding: 10px 15px;
      border: 1px solid #ccc;
      /* 排印 */
      font: normal 13px "Helvetica Neue", sans-serif;
      line-height: 1.5;
      color: #333;
      background-color: #f5f5f5;
      text-align: center;
      }
  • 可以缩写时,建议缩写属性,如font, margin
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /* good */
    .post {
    font: 12px/1.5 arial, sans-serif;
    }

    /* bad */
    .post {
    font-family: arial, sans-serif;
    font-size: 12px;
    line-height: 1.5;
    }
  • 尽量不使用!important声明

字体

  • font-family必须使用字体族的英文名称,其中如有空格等特殊字符,必须使用双引号包裹。
    1
    2
    3
    h1 {
    font-family: "Microsoft YaHei";
    }
  • font-family按效果从优到通用顺序编写
    1
    2
    3
    h1 {
    font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", sans-serif;
    }
  • 需要在Windows平台下显示的内容,font-size禁止小于12px,否则会模糊不清
  • ling-height建议使用数值
    1
    2
    3
    .text {
    line-height: 1.5;
    }
  • 建议减少使用自定义中文字体,通常体积很大,很影响页面加载

响应式

  • 媒体查询必须放在尽可能相关的规则附近,不得单独编排
    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
    /* bad */
    /* header styles */
    /* main styles */
    /* footer styles */

    @media (...) {
    /* header styles */
    /* main styles */
    /* footer styles */
    }

    /* good */
    /* header styles */
    @media (...) {
    /* header styles */
    }

    /* main styles */
    @media (...) {
    /* main styles */
    }

    /* footer styles */
    @media (...) {
    /* footer styles */
    }
  • 媒体查询有多个条件分隔时,每个条件必须另起一行
    1
    2
    3
    4
    5
    6
    7
    @media
    (-webkit-min-device-pixel-ratio: 2), /* Webkit-based browsers */
    (min--moz-device-pixel-ratio: 2), /* Older Firefox browsers (prior to Firefox 16) */
    (min-resolution: 2dppx), /* The standard way */
    (min-resolution: 192dpi) { /* dppx fallback */
    /* Retina-specific stuff here */
    }
  • 媒体查询针对每一个种屏幕(大、中、小)的建议单独组织为一个文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /* base.css */
    .element {
    }
    .element-avatar {
    }
    .element-selected {
    }
    /* base-media-small.css */
    @media (min-width: 480px) {
    .element {
    }
    .element-avatar {
    }
    .element-selected {
    }
    }

其他

  • 禁止使用JavaScript

参考

集团前端代码规约
文档与源码编写风格