基本原則
- 結構、樣式、行為分離
- 統一縮進(建議 兩個空格)
- 文件編碼統一 不帶
BOM
的UTF-8
- 一律使用小寫字母
- 省略外鏈資源 URL 協議部分(FTP等其他URL不省略)
- 統一注釋
HTML
- 標簽
- 自閉合無需閉合
img
input
br
hr
等 - 可選閉合需閉合
- 盡量減少標簽
- 自閉合無需閉合
-
class
&id
- 以功能或內容命名, 不以表現形式命名
- 以
-
分隔
- 屬性順序 id > class > name > data-xxx > src,for,type,href > title,alt > aria-xxx,role
- 屬性統一使用雙引號
- 語義嵌套及嚴格嵌套約束 參考:WEB標準系列-HTML元素嵌套
-
<li>
用于<ul>
或<ol>
下 -
<dd>
<dt>
用于<dl>
下 -
<thead>
<tbody>
<tfoot>
<tr>
<td>
用于<table>
下 - inline-Level 元素,僅可以包含文本或其它 inline-Level 元素;
-
<a>
里不可以嵌套交互式元素<a>
、<button>
、<select>
等; -
<p>
里不可以嵌套塊級元素<div>
、<h1>~<h6>
、<p>
、<ul>/<ol>/<li>
、<dl>/<dt>/<dd>
、<form>
等。
-
-
HEAD
- 文檔類型
<!DOCTYPE html>
- 語言屬性
<lang="zh-cmn-Hans">
- 字符編碼(必須是
<head>
標簽的第一個子元素)<meta charset="utf-8">
- 優先使用最新內核
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-
SEO
優化<meta name="keywords" content="your keywords"> <meta name="description" content="your description"> <meta name="author" content="author,email address">
-
viewport
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
iOS圖標
-
apple-touch-icon
圖片自動處理成圓角和高光等效果; -
apple-touch-icon-precomposed
禁止系統自動添加效果,直接顯示設計原圖;
-
-
favicon
<link rel="shortcut icon" href="path/to/favicon.ico">
- 文檔類型
HEAD模板
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Style Guide</title>
<meta name="description" content="不超過150個字符">
<meta name="keywords" content="">
<meta name="author" content="name, email@gmail.com">
<!-- 為移動設備添加 viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- iOS 圖標 -->
<link rel="apple-touch-icon-precomposed" href="/apple-touch-icon-57x57-precomposed.png">
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
<link rel="shortcut icon" href="path/to/favicon.ico">
</head>
HTML標簽語義化
標簽 | 語義 |
---|---|
<p> |
段落 |
<h1> <h2> <h3> ... |
標題 |
<ul> |
無序列表 |
<ol> |
有序列表 |
<blockquote> |
大段引用 |
<cite> |
一般引用 |
<b>
為樣式加粗而加粗
<storng>
| 為強調內容而加粗
<i>
| 為樣式傾斜而傾斜
<em>
| 為強調內容而傾斜
<code>
| 代碼標識
<abbr>
| 縮寫
CSS
- 以組件為單位組織代碼
- 組件塊和子組件塊以及聲明塊之間使用一空行分隔,子組件塊之間三空行分隔;
- 如果使用了多個 CSS 文件,將其按照組件而非頁面的形式分拆,因為頁面會被重組,而組件只會被移動;
- 避免選擇器嵌套層級過多, 盡量少于3級
- 避免
Class
ID
疊加使用 - 聲明塊
- 選擇器分組時, 保持獨立的選擇器占用一行
- 聲明塊的左括號
{
前添加一個空格; - 聲明塊的右括號
}
應單獨成行; - 聲明語句中的
:
后應添加一個空格; - 聲明語句應以分號
;
結尾; - 一般以逗號分隔的屬性值,每個逗號后應添加一個空格;
- rgb()、rgba()、hsl()、hsla() 或 rect() 括號內的值,逗號分隔,但逗號后不添加一個空格;
- 對于屬性值或顏色參數,省略小于 1 的小數前面的 0 (例如,.5 代替 0.5;-.5px 代替 -0.5px);
- 十六進制值應該全部小寫和盡量簡寫,例如,#fff 代替 #ffffff;
- 避免為 0 值指定單位
- 聲明順序 Positioning > Box model > Typographic > Visual
- url() 、屬性選擇符、屬性值使用雙引號。
- 將媒體查詢(Media query)放在盡可能相關規則的附近
- 不要使用
@import
- 鏈接樣式順序
a:link -> a:visited -> a:hover -> a:active(LoVeHAte)
- 使用Autoprefixer自動添加瀏覽器前綴, 書寫CSS無需添加瀏覽器前綴
/* ==========================================================================
組件塊
============================================================================ */
/* 子組件塊
============================================================================ */
由于定位(positioning)可以從正常的文檔流中移除元素,并且還能覆蓋盒模型(box model)相關的樣式,因此排在首位。盒模型決定了組件的尺寸和位置,因此排在第二位。其他屬性只是影響組件的內部(inside)或者是不影響前兩組屬性。
.declaration-order {
/* Positioning */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
/* Box model */
display: block;
box-sizing: border-box;
width: 100px;
height: 100px;
padding: 10px;
border: 1px solid #e5e5e5;
border-radius: 3px;
margin: 10px;
float: right;
overflow: hidden;
/* Typographic */
font: normal 13px "Helvetica Neue", sans-serif;
line-height: 1.5;
text-align: center;
/* Visual */
background-color: #f5f5f5;
color: #fff;
opacity: .8;
/* Other */
cursor: pointer;
}
CSS 網頁字體排版
字體
內文字體
p { font-family: "Georgia", "Times New Roman", "Songti SC", "SimSun", serif; }
標題字體
h1, h2, h3, h4, h5, h6 { font-family: "Lucida Grande", "Helvetica Neue", "Arial", "Hiragino Sans GB", "Noto Sans CJK SC", "Heiti SC", "Microsoft YaHei", "WenQuanYi Microhei", sans-serif; }
字號
將內文以 16px
作為字號
標題 h1
, h2
, h3
, h4
, h5
, h6
以 16px
作為字號基礎,按同比例的遞減
p { font-size: 16px; }
h1 { font-size: 2em; }
h2 { font-size: 1.8em; }
h3 { font-size: 1.6em; }
h4 { font-size: 1.4em; }
h5, h6 { font-size: 1.2em; }
行高
將內文以 1.7em 作為行高
標題 h1, h2, h3, h4, h5, h6 以 1.5em 作為行高.
p { line-height: 1.7em; }
h1, h2, h3, h4, h5, h6 { line-height: 1.5em; }
段落間距
p { margin-bottom: 1.7em; }
h1, h2, h3, h4, h5, h6 {
margin-top: .7em;
margin-bottom: 0.2em;
}
齊頭尾
p {
text-align: justify;
text-justify: inter-ideographic;
}
斷詞使中英文混排時字符間距不會被齊頭尾拉的不均勻
p { word-break: break-all; }
Less
- 代碼順序 @import > 變量聲明 > 樣式聲明
- @import
.less
不得省略, 用雙引號 - Mixin
- 在定義 mixin 時,如果 mixin 名稱不是一個需要使用的 className,必須加上括號,否則即使不被調用也會輸出到 CSS 中。
- 如果混入的是本身不輸出內容的 mixin,需要在 mixin 后添加括號(即使不傳參數),以區分這是否是一個 className。
- 避免嵌套層級過多, 限制在2層
- 可以使用字符串插值使變量嵌入字符串中
@base-url: "http://assets.fnord.com"; background-image: url("@{base-url}/images/bg.png");
命名(從組件方式思考命名)
- Components 至少以兩個單詞命名,通過
-
分離.like-button
.search-form
.article-card
- Elements (Element 是 Components 中的元素)
- 類名盡可能僅有一個單詞
- 多個單詞應直接連接
- 避免標簽選擇器(性能稍弱,表意不明)
- Variants(變體) 帶有前綴
-
.-wide .-short .-disabled .title.-small
- 避免定位屬性
- Positioning (position, top, left, right, bottom)
- Floats (float, clear)
- Margins (margin)
- Dimensions (width, height)
- 頭像 logos等元素應設置 固定尺寸
- 在父元素中設置定位
- 避免過分嵌套
className命名
常見class關鍵詞:
- 布局類:header, footer, container, main, content, aside, page, section
- 包裹類:wrap, inner
- 區塊類:region, block, box
- 結構類:hd, bd, ft, top, bottom, left, right, middle, col, row, grid, span
- 列表類:list, item, field
- 主次類:primary, secondary, sub, minor
- 大小類:s, m, l, xl, large, small
- 狀態類:active, current, checked, hover, fail, success, warn, error, on, off
- 導航類:nav, prev, next, breadcrumb, forward, back, indicator, paging, first, last
- 交互類:tips, alert, modal, pop, panel, tabs, accordion, slide, scroll, overlay,
- 星級類:rate, star
- 分割類:group, seperate, divider
- 等分類:full, half, third, quarter
- 表格類:table, tr, td, cell, row
- 圖片類:img, thumbnail, original, album, gallery
- 語言類:cn, en
- 論壇類:forum, bbs, topic, post
- 方向類:up, down, left, right
- 其他語義類:btn, close, ok, cancel, switch; link, title, info, intro, more, icon; form, label, search, contact, phone, date, email, user; view, loading…
簡單規則
- 以中劃線連接,如.item-img
- 使用 兩個中劃線表示特殊化,如.item-img.item-img--small表示在.item-img的基礎上特殊化
- 狀態類直接使用單詞,參考上面的關鍵詞,如.active, .checked
- 圖標以icon-為前綴(字體圖標采用.icon-font.i-name方式命名)。
- 模塊采用關鍵詞命名,如.slide, .modal, .tips, .tabs,特殊化采用上面兩個中劃線表示,如.imgslide--full, .modal--pay, .tips--up, .tabs--simple
- js操作的類統一加上js-前綴
- 不要超過四個class組合使用,如.a.b.c.d
JavaScript
- 注釋 如無必要勿增注釋, 如有必要盡量詳盡, 只使用
//
, 避免使用/*...*/
- 函數方法注釋包含函數說明參數和返回值及返回值類型, 如果函數是內部函數可以使用
@inner
標識 - 文件注釋 應該提供文件的大體內容, 它的作者, 依賴關系和兼容性信息。如下:
- 函數方法注釋包含函數說明參數和返回值及返回值類型, 如果函數是內部函數可以使用
/**
* 函數描述
*
* @param {string} p1 參數1的說明
* @param {string} p2 參數2的說明,比較長
* 那就換行了.
* @param {number=} p3 參數3的說明(可選)
* @return {Object} 返回值描述
*/
/**
* @fileoverview Description of file, its uses and information
* about its dependencies.
* @author user@meizu.com (Firstname Lastname)
* Copyright 2009 Meizu Inc. All Rights Reserved.
*/
- 命名
- 變量 駝峰命名法
- 私有屬性變量方法
_
開頭 - 常量 全部字母大寫,
_
分隔 - 函數及函數的參數 駝峰命名法
- 類 單詞首字母大寫, 類的方法及屬性 駝峰命名法
- 枚舉變量 單詞首字母大寫, 枚舉屬性 全部字母大寫,
_
分隔 - 多個單詞組成的縮寫詞, 在命名中, 根據當前命名法和出現的位置, 所有字母的大小寫與首字母大小寫保持一致
- 命名詞法
- 類名 使用名詞
function Engine(options) {}
- 函數名,使用動賓短語。
function getStyle(element) {}
-
boolean類型的變量 使用 is 或 has 開頭。
var isReady = false; var hasMoreCommands = false;
- Promise 對象用動賓短語的進行時表達。
var loadingData = ajax.get('url'); loadingData.then(callback);
- 類名 使用名詞
- 接口命名規范 (1.可讀性強 2.不與
jQuery
社區習慣沖突 3.盡量寫全不用縮寫,除非下表中已經約定的)
常用詞 | 說明 |
---|---|
options | 表示選項,與 jQuery 社區保持一致,不要用 config, opts 等 |
active | 表示當前,不要用 current 等 |
index | 表示索引,不要用 idx 等 |
trigger | 觸點元素 |
triggerType | 觸發類型、方式 |
context | 表示傳入的 this 對象 |
object | 推薦寫全,不推薦簡寫為 o, obj 等 |
element | 推薦寫全,不推薦簡寫為 el, elem 等 |
length | 不要寫成 len, l |
prev | previous 的縮寫 |
next | next 下一個 |
constructor | 不能寫成 ctor |
easing | 示動畫平滑函數 |
min | minimize 的縮寫 |
max | maximize 的縮寫 |
DOM | 不要寫成 dom, Dom |
.hbs | 使用 hbs 后綴表示模版 |
btn | button 的縮寫 |
link | 超鏈接 |
title | 主要文本 |
img | 圖片路徑(img標簽src屬性) |
dataset | html5 data-xxx 數據接口 |
theme | 主題 |
className | 類名 |
classNameSpace | class 命名空間 |
- True False
- 類型檢測 優先使用
typeof
- 對象檢測 使用
instanceof
- null 或 undefined 檢測使用
== null
- 返回 false
null
undefined
''
0
- 返回 true
'0'
[]
{}
- 類型檢測 優先使用
-
for-in
循環只用于object/map/hash
遍歷, 因為Array
上使用for-in
循環會對所有出現在原型上的對象進行遍歷 - 二元及三元操作符始終寫在前一行
- 三元操作符替代
if...else
-
&&
||
設置默認值和替代多個if
嵌套判斷 - 正則表達式 僅準用
.test()
和.exec()
。不準用"string".match()
- 多個參數使用對象字面量存儲
jQuery
- 使用最新版本的jQuery
- jQuery變量 以
$
開頭, 并緩存到本地變量中復用, 使用駝峰命名法命名 - jQuery選擇器
- 盡量使用ID選擇器
- 父元素選擇子元素用
.find()
方法性能會更好
- DOM 操作, 盡量先與節點分離, 操作結束后再插入節點
- 字符串連接
array.join('')
>+
>.append()
- 事件
- 如果需要,對事件使用自定義的 namespace,這樣容易解綁特定的事件,而不會影響到此 DOM 元素的其他事件監聽;
- 對 Ajax 加載的 DOM 元素綁定事件時盡量使用事件委托。事件委托允許在父元素綁定事件,子代元素可以響應事件,也包括 Ajax 加載后添加的子代元素;
$("#myLink").on("click.mySpecialClick", myEventHandler);
$("#myLink").unbind("click.mySpecialClick");
// Not recommended
$("#list a").on("click", myClickHandler);
// Recommended
$("#list").on("click", "a", myClickHandler);
- 鏈式寫法 1.盡量使用鏈式寫法而不是用變量緩存或者多次調用選擇器方法; 2.當鏈式寫法超過三次或者因為事件綁定變得復雜后,使用換行和縮進保持代碼可讀性;
-
CSS
不要寫在jQuery
里面 - 避免使用
jQuery
實現動畫- 禁止使用
slideUp/Down() fadeIn/fadeOut()
等方法; - 盡量不使用
animate()
方法;
- 禁止使用
jQuery 插件模板
// jQuery Plugin Boilerplate
// A boilerplate for jumpstarting jQuery plugins development
// version 1.1, May 14th, 2011
// by Stefan Gabos
// remember to change every instance of "pluginName" to the name of your plugin!
(function($) {
// here we go!
$.pluginName = function(element, options) {
// plugin's default options
// this is private property and is accessible only from inside the plugin
var defaults = {
foo: 'bar',
// if your plugin is event-driven, you may provide callback capabilities
// for its events. execute these functions before or after events of your
// plugin, so that users may customize those particular events without
// changing the plugin's code
onFoo: function() {}
}
// to avoid confusions, use "plugin" to reference the
// current instance of the object
var plugin = this;
// this will hold the merged default, and user-provided options
// plugin's properties will be available through this object like:
// plugin.settings.propertyName from inside the plugin or
// element.data('pluginName').settings.propertyName from outside the plugin,
// where "element" is the element the plugin is attached to;
plugin.settings = {}
var $element = $(element), // reference to the jQuery version of DOM element
element = element; // reference to the actual DOM element
// the "constructor" method that gets called when the object is created
plugin.init = function() {
// the plugin's final properties are the merged default and
// user-provided options (if any)
plugin.settings = $.extend({}, defaults, options);
// code goes here
}
// public methods
// these methods can be called like:
// plugin.methodName(arg1, arg2, ... argn) from inside the plugin or
// element.data('pluginName').publicMethod(arg1, arg2, ... argn) from outside
// the plugin, where "element" is the element the plugin is attached to;
// a public method. for demonstration purposes only - remove it!
plugin.foo_public_method = function() {
// code goes here
}
// private methods
// these methods can be called only from inside the plugin like:
// methodName(arg1, arg2, ... argn)
// a private method. for demonstration purposes only - remove it!
var foo_private_method = function() {
// code goes here
}
// fire up the plugin!
// call the "constructor" method
plugin.init();
}
// add the plugin to the jQuery.fn object
$.fn.pluginName = function(options) {
// iterate through the DOM elements we are attaching the plugin to
return this.each(function() {
// if plugin has not already been attached to the element
if (undefined == $(this).data('pluginName')) {
// create a new instance of the plugin
// pass the DOM element and the user-provided options as arguments
var plugin = new $.pluginName(this, options);
// in the jQuery version of the element
// store a reference to the plugin object
// you can later access the plugin and its methods and properties like
// element.data('pluginName').publicMethod(arg1, arg2, ... argn) or
// element.data('pluginName').settings.propertyName
$(this).data('pluginName', plugin);
}
});
}
})(jQuery);
ES6
- 塊級作用域
-
let
取代var
-
let
const
優先使用const
(所有的函數應設置為const常量
,let
表示的變量,只應出現在單線程運行的代碼中,不能是多線程共享的,這樣有利于保證線程安全。)
-
- 字符串
- 靜態字符串使用單引號
- 動態字符串使用反引號
- 解構賦值
- 數組成員賦值,優先使用解構賦值
const [first, second] = [1, 2];
- 函數的參數如果是對象的成員,優先使用解構賦值。
- 如果函數返回多個值,優先使用對象的解構賦值,而不是數組的解構賦值。
- 數組成員賦值,優先使用解構賦值
- 對象
- 單行定義的對象,最后一個成員不以逗號結尾
- 多行定義的對象,最后一個成員以逗號結尾
- 對象盡量靜態化,不得隨意添加屬性.如果添加屬性不可避免,使用
Object.assign()
- 如果對象的屬性名是動態的,可以在創造對象的時候,使用屬性表達式定義。
- 對象屬性和方法盡量采用簡潔表達法
- 數組
- 使用擴展運算符
...
拷貝數組 - 使用
Array.from()
將類數組對象轉為數組
- 使用擴展運算符
- 函數
- 立即執行函數可以寫成箭頭函數
(()=>{console.log('a');})()
- 能用箭頭函數盡量用箭頭函數,不僅簡潔而且綁定了
this
- 箭頭函數取代
Function.prototype.bind
,不應再用self/_this/that
綁定this
。 - 所有配置項都應該集中在一個對象,放在最后一個參數,布爾值不可以直接作為參數。
- 不要在函數體內使用
arguments
變量,使用rest運算符(...)
代替。 - 使用默認值語法設置函數參數的默認值。
- 立即執行函數可以寫成箭頭函數
-
Map
結構- 只有模擬實體對象時,才使用
Object
。如果只是需要key:value
的數據結構,使用Map
。因為Map
有內建的遍歷機制。
- 只有模擬實體對象時,才使用
- class
- 用
class
取代prototype
操作 - 使用
extends
實現繼承,這樣不會有破壞instanceof
運算的危險。
- 用
- module
-
import
取代require
-
export
取代module.exports
- 如果模塊只有一個輸出值,就使用
export default
,如果模塊有多個輸出值,就不使用export default
,不要export default
與普通的export
同時使用。 - 不要在模塊輸入中使用通配符。因為這樣可以確保你的模塊之中,有一個默認輸出(
export default
)。 - 模塊輸出函數, 函數首字母小寫
- 模塊輸出對象,對象首字母大寫
-
代碼校驗
代碼驗證
- 使用 W3C HTML Validator 來驗證你的HTML代碼有效性;
- 使用 W3C CSS Validator 來驗證你的CSS代碼有效性;
ESlint 使用
$ npm i -g eslint
$ npm i -g eslint-config-airbnb
-
.eslintrc
文件,配置ESLint。{"extends": "eslint-config-airbnb"}