參見文檔:https://github.com/doyoe/html-css-guide
1.文檔目錄結構
|-- 項目名 |-- src 開發環境 |-- html 靜態頁面模板目錄 |-- bgimg 背景圖目錄(假設有的話) |-- image 前景圖目錄(假設有的話) |-- font 字體目錄(假設有的話) |-- scripts 腳本目錄 |-- styles(Yo) 樣式目錄 |-- lib 基礎庫 |-- core 核心代碼:reset |-- element 元素 |-- fragment 公用碎片 |-- layout 布局 |-- widget 組件 |-- usage 項目具體實現 |-- project 某個子項目 |-- core 核心代碼:橋接lib中的core,可以進行項目級擴展 |-- fragment 項目公用碎片 |-- module 模塊 |-- page page橋接文件目錄:src-list |-- export page pack之后的文件目錄 |-- prd 生產環境 |-- bgimg 背景圖目錄(假設有的話) |-- image 前景圖目錄(假設有的話) |-- font 字體目錄(假設有的話) |-- scripts 腳本目錄 |-- styles(Yo) 樣式目錄 |-- project1 子項目 |-- index.css |-- login.css |-- and etc... |-- project2 子項目 |-- index.css |-- login.css |-- and etc... |-- and etc...
src, scripts, styles 三個目錄是為了和現有項目保持一致,避免修改過大,所以保持不變。 html 目錄,用於存放前端開發做的靜態頁面,以備查閱、備份、review或給后端套頁面。 bgimg, image, font 三個目錄在Qunar一般不會直接存在,因為我們有source服務器,這些資源都會在那上面管理;不過特殊情況也會有,比如一些獨立的項目,沒有使用source的,那么就需要遵循這樣的目錄划分。 至於 html, bgimg, image, font 這幾個目錄為什么沒有加 s,主要是因為不希望大家去想某個目錄是否為復數,簡單點就好。 prd 為生產環境目錄,以 xxx 項目中的一個子項目 mobile 為例,其生產環境中的某個CSS外鏈大致如下://sitename.com/prd/styles/mobile/index.css
2.分離
結構(HTML)、表現(CSS)、行為分離(JavaScript)
將結構與表現、行為分離,保證它們之間的最小耦合,這對前期開發和后期維護都至關重要。
3.文件命名
CSS模塊文件,其文件名必須與模塊名一致;
假定有這樣一個模塊:
.m-detail { sRules; }
.m-detail-hd { sRules; }
.m-detail-bd { sRules; }
.m-detail-ft { sRules; }
那么該模塊的文件名應該為:m-detail.css
CSS頁面文件,其文件名必須與HTML文件名一致;
假定有一個HTML頁面叫 product.html,那么其相對應的CSS頁面文件名應該為:product.css
假定現在有一個 product.html,里面有2個模塊:
+<section class="m-list"> +<section class="m-info">
那么開發人員能快速找到與該頁面相關的3個直接CSS文件,包括:product.css, m-list.css, m-info.css
4.縮進
使用tab(4個空格寬度)來進行縮進,可以在IDE里進行設置
5.編碼
以 UTF-8 無 BOM 編碼作為文件格式;
在HTML中文檔中用 <meta charset="utf-8" /> 來指定編碼;
為每個CSS文檔顯示的定義編碼,在文檔首行定義 @charset "utf-8";
在 Sass 中,如果文檔中出現中文,卻未顯示定義編碼,將會編譯出錯,為了統一各種寫法,且提前規避錯誤幾率,統一要求每個CSS文檔都需要定義編碼
6.小寫
所有的HTML標簽必須小寫;
所有的HTML屬性必須小寫;
所有的樣式名及規則必須小寫。
7.注釋
盡可能的為你的代碼寫上注釋。解釋為什么要這樣寫,它是新鮮的方案還是解決了什么問題。
8.待辦事項
用 TODO 標示待辦事項和正在開發的條目
<!-- TODO: 圖文混排 -->
<div class="g-imgtext">
<img src="1.png" alt="" /> ... /* TODO: 圖文混排 comm: g-imgtext */ .g-imgtext { sRules; }
9.行尾空格
刪除行尾空格,這些空格沒有必要存在
10.省略嵌入式資源協議頭
省略圖像、媒體文件、樣式表和腳本等URL協議頭部聲明 ( http: , https: )。如果不是這兩個聲明的URL則不省略。
省略協議聲明,使URL成相對地址,防止內容混淆問題和導致小文件重復下載(這個主要是指http和https交雜的場景中)。
不推薦:
<script src="http://www.google.com/js/gweb/analytics/autotrack.js"></script>
推薦:
<script src="//www.google.com/js/gweb/analytics/autotrack.js"></script>
不推薦:
.example { background: url(http://www.google.com/images/example);
}
推薦:
.example {
background: url(//www.google.com/images/example);
}
注:省略協議頭在IE7-8下會有一點小問題,外部CSS文件(link和@import)會被下載兩遍,所以該條目的約定看具體項目。
HTML約定
1.文檔類型
統一使用HTML5的標准文檔類型:<!DOCTYPE html>;
HTML5文檔類型具備前后兼容的特質,並且易記易書寫
在文檔doctype申明之前,不允許加上任何非空字符;
任何出現在doctype申明之前的字符都將使得你的HTML文檔進入非標准模式
不允許添加 <meta> 標簽強制改變文檔模式。
避免出現不可控的問題
2.省略type屬性
在調用CSS和JavaScript時,可以將type屬性省略不寫
不允許:
<link type="text/css" rel="stylesheet" href="base.css" />
<script type="text/javascript" src="base.js"></script>
應該:
<link rel="stylesheet" href="base.css" />
<script src="base.js"></script> 因為HTML5在引入CSS時,默認type值為text/css;在引入JavaScript時,默認type值為text/javascript
3.省略屬性值
非必須屬性值可以省略
不允許:
<input type="text" readonly="readonly" />
<input type="text" disabled="disabled" />
應該:
<input type="text" readonly />
<input type="text" disabled /> 這里的 readonly 和 disabled 屬性的值是非必須的,可以省略不寫,我們知道HTML5表單元素新增了很多類似的屬性,如: required
4.用雙引號包裹屬性值
所有的標簽屬性值必須要用雙引號包裹,同時也不允許有的用雙引號,有的用單引號的情況
不允許:
<a href=http://www.qunar.com class="home">去哪兒網</a>
應該:
<a href="http://www.qunar.com" class="home">去哪兒網</a>
5.嵌套
所有元素必須正確嵌套
不允許交叉;
不允許:
<span><dfn>交叉嵌套</span></dfn>
應該:
<span><dfn>交叉嵌套</dfn></span> 不允許非法的子元素嵌套。
不允許:
<ul>
<h3>xx列表</h3>
<li>asdasdsdasd</li>
<li>asdasdsdasd</li>
</ul>
應該:
<div>
<h3>xx列表</h3>
<ul>
<li>asdasdsdasd</li>
<li>asdasdsdasd</li>
</ul>
</div>
不推薦inline元素包含block元素;
不推薦:
<span>
<h1>這是一個塊級h1元素</h1>
<p>這是一個塊級p元素</p>
</span>
推薦:
<div>
<h1>這是一個塊級h1元素</h1>
<p>這是一個塊級p元素</p>
</div>
6.標簽閉合
所有標簽必須閉合
不允許:
<div>balabala... <link rel="stylesheet" href="*.css">
應該:
<div>balabala...</div>
<link rel="stylesheet" href="*.css" /> 雖然有些標記沒有要求必須關閉,但是為了避免出錯的幾率,要求必須全部關閉,省去判斷某標記是否需要關閉的時間
7.多媒體替代方案
為img元素加上alt屬性;
為視頻內容提供音軌替代;
為音頻內容提供字母替代等等。
不推薦:
<img src="banner.jpg" />
推薦:
<img src="banner.jpg" alt="520即將到來,愛就大聲說出來" /> alt屬性的內容為對該圖片的簡要描述,這對於盲人用戶和圖像損毀都非常有意義,即無障礙。對於純粹的裝飾性圖片,alt屬性值可以留空,如 alt=""
8.有效操作
為表單元素label加上for屬性
不允許:
<input type="radio" name="color" value="0" /><label>藍色</label>
<input type="radio" name="color" value="1" /><label>粉色</label>
應該:
<input type="radio" id="blue" name="color" value="0" /><label for="blue">藍色</label>
<input type="radio" id="pink" name="color" value="1" /><label for="pink">粉色</label> for屬性能讓點擊label標簽的時候,同時focus到對應的 input 和 textarea上,增加響應區域
9.按模塊添加注釋
在每個模塊開始和結束的地方添加注釋
<!-- 新聞列表模塊 -->
<div class="m-news g-mod" ... <!-- /新聞列表模塊 -->
<!-- 排行榜模塊 -->
<div class="m-topic g-mod" ... <!-- /排行榜模塊 --> 注釋內容左右兩邊保留和注釋符號有1個空格位,在注釋內容內不允許再出現中划線“-”,某些瀏覽器會報錯。 注釋風格保持與原生HTML的語法相似:成對出現 <!-- comment --><!-- /comment -->
10.格式
將每個塊元素、列表元素或表格元素都放在新行;
inline元素視情況換行,以長度不超過編輯器一屏為宜;
每個子元素都需要相對其父級縮進(參見縮進約定)。
不推薦:
<div><h1>asdas</h1><p>dff<em>asd</em>asda<span>sds</span>dasdasd</p></div>
推薦:
<div>
<h1>asdas</h1>
<p>dff<em>asd</em>asda<span>sds</span>dasdasd</p>
</div>
11.語義化標簽
根據HTML元素的本身用途去使用它們;
禁止使用被廢棄的用於表現的標簽,如 center, font 等;
部分在XHTML1中被廢棄的標簽,在HTML5中被重新賦予了新的語義,在選用時請先弄清其語義,如:b, i, u等。
不允許:
<p>標題</p>
應該:
<h1>標題</h1>
雖然使用p標簽,也可以通過CSS去定義它的外觀和標題相同,但p標簽本身的並不是表示標題,而是表示文本段落
參閱:HTML5 Elements
12.模塊化
每個模塊必須有一個模塊名;
每個模塊的基本組成部分應該一致;
模塊的子節點類名需帶上模塊名(防止模塊間嵌套時產生不必要的覆蓋);
孫輩節點無需再帶模塊名。
代碼如:
<section class="m-detail">
<header class="m-detail-hd">
<h1 class="title">模塊標題</h1>
</header>
<div class="m-detail-bd">
<p class="info">一些實際內容</p>
</div>
<footer class="m-detail-ft">
<a href="#" class="more">更多</a>
</footer>
</section>
其中 .m-detail-hd, .m-detail-bd, .m-detail-ft 為可選,視具體模塊情況決定是否需要抽象為這種 頭,中,尾 的結構
CSS約定
1.文件引用
一律使用link的方式調用外部樣式
不允許在頁面中使用 <style> 塊;
不允許在 <style> 塊中使用 @import;
不允許使用 style 屬性寫行內樣式。
一般情況下,在頁面中只允許使用 <link /> 標簽來引用CSS文件,
2.命名-組成元素
命名必須由單詞、中划線①或數字組成;
不允許使用拼音(約定俗成的除外,如:youku, baidu),尤其是縮寫的拼音、拼音與英文的混合。
不推薦:
.xiangqing { sRules; }
.news_list { sRules; }
.zhuti { sRules; }
推薦:
.detail { sRules; } .news-list { sRules; } .topic { sRules; }
①我們使用中划線 “-” 作為連接字符,而不是下划線 "_"。
我們知道2種方式都有不少支持者,但 "-" 能讓你少按一次shift鍵,並且更符合CSS原生語法,所以我們只選一種目前業內普遍使用的方式
3.命名-詞匯規范
不依據表現形式來命名;
可根據內容來命名;
可根據功能來命名。
不推薦:
left, right, center, red, black
推薦:
nav, aside, news, type, search
4.命名-縮寫規范
保證縮寫后還能較為清晰保持原單詞所能表述的意思;
使用業界熟知的或者約定俗成的。
不推薦:
navigation => navi header => head description => des
推薦:
navigation => nav header => hd description => desc
5.命名-前綴規范
前綴 說明 示例
g- 全局通用樣式命名,前綴g全稱為global,一旦修改將影響全站樣式 g-mod
m- 模塊命名方式 m-detail
ui- 組件命名方式 ui-selector
js- 所有用於純交互的命名,不涉及任何樣式規則。JSer擁有全部定義權限 js-switch
選擇器必須是以某個前綴開頭
不推薦:
.info { sRules; }
.current { sRules; }
.news { sRules; }
因為這樣將給我們帶來不可預知的管理麻煩以及沉重的歷史包袱。你永遠也不會知道哪些樣式名已經被用掉了,如果你是一個新人,你可能會遭遇,你每定義個樣式名,都有同名的樣式已存在,然后你只能是換樣式名或者覆蓋規則。
推薦:
.m-detail .info { sRules; } .m-detail .current { sRules; } .m-detail .news { sRules; }
所有的選擇器必須是以 g-, m-, ui- 等有前綴的選擇符開頭的,意思就是說所有的規則都必須在某個相對的作用域下才生效,盡可能減少全局污染。
js- 這種級別的className完全交由JSer自定義,但是命名的規則也可以保持跟重構一致,比如說不能使用拼音之類的
6.id與class
重構工程師只允許使用class(因歷史原因及大家的習慣做出妥協)。
7.書寫格式
選擇器與大括號之間保留一個空格;
分號之后保留一個空格;
逗號之后保留一個空格;
所有規則需換行;
多組選擇器之間需換行。
不推薦:
main{ display:inline-block; } h1,h2,h3{ margin:0; background-color:rgba(0,0,0,.5); }
推薦:
main { display: inline-block; } h1,
h2,
h3 { margin: 0; background-color: rgba(0, 0, 0, .5); }
8.規則與分號
每條規則結束后都必須加上分號
不推薦:
body { margin: 0; padding: 0; font-size: 14px }
推薦:
body { margin: 0; padding: 0; font-size: 14px; }
9.0與單位
如果屬性值為0,則不需要為0加單位
不推薦:
body {
margin: 0px;
padding: 0px;
}
推薦:
body { margin: 0; padding: 0; }
10.0與小數
如果是0開始的小數,前面的0可以省略不寫
不推薦:
body { opacity: 0.6; text-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5); }
推薦:
body { opacity: .6; text-shadow: 1px 1px 5px rgba(0, 0, 0, .5); }
11.去掉uri中引用資源的引號
不要在url()里對引用資源加引號
不推薦:
body { background-image: url("sprites.png"); } @import url("global.css");
推薦:
body { background-image: url(sprites.png); } @import url(global.css);
12.HEX顏色值寫法
將所有的顏色值小寫;
可以縮寫的縮寫至3位。
不推薦:
body { background-color: #FF0000; }
推薦:
body { background-color: #f00; }
13.屬性書寫順序
遵循先布局后內容的順序。
.g-box { display: block; float: left; width: 500px; height: 200px; margin: 10px; padding: 10px; border: 10px solid; background: #aaa; color: #000; font: 14px/1.5 sans-serif;
}
這個應該好理解,比如優先布局,我們知道布局屬性有 display, float, overflow 等等;內容次之,比如 color, font, text-align 之類。
組概念。
拿上例的代碼來說,如果我們還需要進行定位及堆疊,規則我們可以改成如下:
.g-box { display: block; position: relative; z-index: 2; top: 10px; left: 100px; float: left; width: 500px; height: 200px; margin: 10px; padding: 10px; border: 10px solid; background: #aaa; color: #000; font: 14px/1.5 sans-serif;
}
從代碼中可以看到,我們直接將z-index, top, left 緊跟在 position 之后,因為這幾個屬性其實是一組的,如果去掉position,則后3條屬性規則都將失效。
私有屬性在前標准屬性在后
.g-box { -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, .5); -moz-box-shadow: 1px 1px 5px rgba(0, 0, 0, .5); -o-box-shadow: 1px 1px 5px rgba(0, 0, 0, .5); box-shadow: 1px 1px 5px rgba(0, 0, 0, .5); }
當有一天你的瀏覽器升級后,可能不再支持私有寫法,那么這時寫在后面的標准寫法將生效,避免無法向后兼容的情況發生。
14.注釋規范
保持注釋內容與星號之間有一個空格的距離
普通注釋(單行)
/* 普通注釋 */
區塊注釋
/** * 模塊: m-detail * 描述:酒店詳情模塊 * 應用:page detail, info and etc...etc */
有特殊作用的規則一定要有注釋說明 應用了高級技巧的地方一定要注釋說明
15.hack規范
盡可能的減少對Hack的使用和依賴,如果在項目中對Hack的使用太多太復雜,對項目的維護將是一個巨大的挑戰;
使用其它的解決方案代替Hack思路;
如果非Hack不可,選擇穩定且常用並易於理解的。
.test { color: #000; /* For all */ color: #111\9; /* For all IE */ color: #222\0; /* For IE8 and later, Opera without Webkit */ color: #333\9\0; /* For IE8 and later */ color: #444\0/; /* For IE8 and later */
*color: #666; /* For IE7 and earlier */ _color: #777; /* For IE6 and earlier */ }
嚴謹且長期的項目,針對IE可以使用條件注釋作為預留Hack或者在當前使用
IE條件注釋語法:
<!--[if <keywords>? IE <version>?]>
<link rel="stylesheet" href="*.css" />
<![endif]-->
語法說明:
<keywords> if條件共包含6種選擇方式:是否、大於、大於或等於、小於、小於或等於、非指定版本 是否:指定是否IE或IE某個版本。關鍵字:空 大於:選擇大於指定版本的IE版本。關鍵字:gt(greater than) 大於或等於:選擇大於或等於指定版本的IE版本。關鍵字:gte(greater than or equal) 小於:選擇小於指定版本的IE版本。關鍵字:lt(less than) 小於或等於:選擇小於或等於指定版本的IE版本。關鍵字:lte(less than or equal) 非指定版本:選擇除指定版本外的所有IE版本。關鍵字:!
<version> 目前的常用IE版本為6.0及以上,推薦酌情忽略低版本,把精力花在為使用高級瀏覽器的用戶提供更好的體驗上,另從IE10開始已無此特性
16.避免低效率選擇器
避免類型選擇器
不允許:
div#doc { sRules; }
li.first { sRules; }
應該:
#doc { sRules; }
.first { sRules; }
CSS選擇器是由右到左進行解析的,所以 div#doc 本身並不會比 #doc 更快
避免多id選擇器
不允許:
#xxx #yyy { sRules; }
應該:
#yyy { sRules; }
17.屬性縮寫與分拆
無繼承關系時,使用縮寫
不推薦:
body { margin-top: 10px; margin-right: 10px; margin-bottom: 10px; margin-left: 10px; }
推薦:
body {
margin: 10px;
}
存在繼承關系時,使用分拆方式
不推薦:
.m-detail { font: bold 12px/1.5 arial, sans-serif;
} .m-detail .info { font: normal 14px/1.5 arial, sans-serif;
}
要避免錯誤的覆蓋:
.m-detail .info { font: 14px sans; }
如果你只是想改字號和字體,然后寫成了上面這樣,這是錯誤的寫法,因為 font 復合屬性里的其他屬性將會被重置為 user agent 的默認值,比如 font-weight 就會被重置為 normal。
推薦:
.m-detail { font: bold 12px/1.5 arial, sans-serif;
} .m-detail .info { font-weight: normal; font-size: 14px; }
在存在繼承關系的情況下,只將需要變更的屬性重定義,不進行縮寫,避免不需要的重寫的屬性被覆蓋定義
根據規則條數選擇縮寫和拆分
不推薦:
.m-detail { border-width: 1px; border-style: solid; border-color: #000 #000 #f00; }
推薦:
.m-detail { border: 1px solid #000; border-bottom-color: #f00; }
18.模塊化
每個模塊必須是一個獨立的樣式文件,文件名與模塊名一致;
模塊樣式的選擇器必須以模塊名開頭以作范圍約定;
假定有一個模塊如前文 HTML模塊化,那么 m-detail.scss 的寫法大致如下:
.m-detail { background: #fff; color: #333; &-hd { padding: 5px 10px; background: #eee; .title { background: #eee; } } &-bd { padding: 10px; .info { font-size: 14px; text-indent: 2em; } } &-ft { text-align: center; .more { color: blue; } } }
編譯之后代碼如下:
.m-detail { background: #fff; color: #333; } .m-detail-hd { padding: 5px 10px; background: #eee; } .m-detail-hd .title { background: #eee; } .m-detail-bd { padding: 10px; } .m-detail-bd .info { font-size: 14px; text-indent: 2em; } .m-detail-ft { text-align: center; } .m-detail-ft .more { color: blue; }
任何超過3級的選擇器,需要思考是否必要,是否有無歧義的,能唯一命中的更簡短的寫法
圖像約定
1.圖像壓縮
所有圖片必須經過一定的壓縮和優化才能發布
2.背景圖
使用PNG格式而不是GIF格式,因為PNG格式色彩更豐富,還能提供更好的壓縮比; 在需要兼容IE6的項目中,盡可能選擇PNG8,而不是使用PNG24+濾鏡。
3.前景圖
內容圖片建議使用JPG,可以擁有更好地顯示效果;
裝飾性圖片使用PNG。
4.Sprite
CSS Sprite是一種將數個圖片合成為一張大圖的技術(既可以是背景圖也可以是前景圖),然后通過偏移來進行圖像位置選取;
CSS Sprite可以減少http請求。