我們平時最開始學習寫 CSS 代碼的時候,我們都是這麼寫的:
.main-part .tabs {
/*...*/
}
其實這樣的寫法是不好的,因為它過度的與頁面中的某一部分耦合了。我們在軟件工程的思想中追求的就是解耦。
BEM 風格不只一種
BEM 的命名規範不是死的,可以參考 bem-conventions
這裡有一些可供選擇的基於 BEM 命名約定的方案。
Two Dashes style(雙連字符風格)
block-name__elem-name--mod-name
- 名字全部使用小寫。
- BEM 實體的名稱中的每一個單詞使用一個連字符分隔。
- 使用雙下划線(__)將元素的名稱和模塊的名稱分離開。
- 使用雙連字符(–)分隔 Boolean 類型的修飾符。
- 不使用 key-value 類型的修飾符
- 重要提示!在注釋中,雙連字符被視為注釋的一部分,因此在文檔驗證時,雙破折號可能會引起錯誤。HTML5 Specification
CamelCase style(駝峰命名風格)
MyBlock__SomeElem_modName_modVla
這種風格的命名方案的不同點在於,在 BEM 實體中分隔單詞時使用駝峰命名法代替了一個連字符(-)。
“Sans underscore” style(無下划線風格)
blockName-elemName--modName--modVal
名稱使用駝峰命名法書寫。 元素名稱與模塊名稱使用一個連字符(-)分隔。 修飾符使用雙連字符(–)與模塊或元素分隔, 修飾符的名稱和值使用雙連字符(–)分隔。 重要提示!
在注釋中,雙連字符被視為注釋的一部分,因此在文檔驗證時,雙破折號可能會引起錯誤。HTML5 Specification
BEM 說明(這裡用 Two Dashes style(雙連字符風格))說明
在這邊使用 BEM 的命名規範,每行 CSS 代碼都只有一個選擇器
BEM代表 區塊(block),元素(element),修飾符(modifier)」,我們常用這三個實體開發組件。
在選擇器中,由以下三種符合來表示擴展的關係:
- dash :僅作為連字符使用,表示某個塊或者某個子元素的多單詞之間的連接記號。
__ Two underline:雙下划線用來連接塊和塊的子元素
-- Two dash:雙減號用來描述一個塊或者塊的子元素的一種狀態
type-block__element--modifier
區塊(block)
一個區塊是設計或佈局的一部分,它有具體且唯一地意義 ,要麼是語義上的要麼是視覺上的。
在大多數情況下,任何獨立的頁面元素(或複雜或簡單)都可以被視作一個區塊。它的HTML容器會有一個唯一的CSS類名,也就是這個區塊的名字。
針對塊的CSS類名會加一些前綴( ui-
),這些前綴在CSS中有類似 name space 的作用。
一個區塊的定義有下面三個基本原則:
- CSS中只能使用類名(不能是ID)。
- 每一個區塊名應該有一個命名空間(前綴)
- 每一條CSS規則必須屬於一個區塊。
例如:一個自定義列表 .product
是一個區塊,通常自定義列表是算在 mod
類別的,在這種情況下,一個 product
列表的block寫法應該為:
.product
元素(element)
塊中的子元素是塊的子元素,並且子元素的子元素在 BEM
里也被認為是塊的直接子元素。一個塊中元素的類名必須用父級塊的名稱作為前綴。
如上面的例子,li.item
是列表的一個子元素,
.list{}
.list .item{}
.list{}
.list__item{}
這裡可以使用偽嵌套寫成
.list {
&__item {}
}
修飾符(modifier)
一個「修飾符」可以理解為一個塊的特定狀態,標識著它持有一個特定的屬性。
用一個例子來解釋最好不過了。一個表示按鈕的塊默認有三個大小:小,中,大。為了避免創建三個不同的塊,最好是在塊上加修飾符。這個修飾符應該有個名字(比如:size
)和值( small
,normal
或者 big
)。
如上面的例子中,表示一個選中的列表,和一個激活的列表項
原本的寫法
.list {}
.list.select {}
.list .item {}
.list .item.active {}
用 BEM 的寫法
.list {}
.list--select {}
.list__item {}
.list__item--active {}
用偽嵌套優化之後為
.list {
&--select {}
&__item {
&--active {}
}
}
使用偽嵌套
使用 &
符號進行偽嵌套
.product {}
.product__item {}
等同於
.product {
&__item {}
}
嵌套不得大於兩層
原則以 B + E + M 完成,不得使用 B + E + E + M,或是 B + B + E + M 之類的寫法
兩層是指從 sass compiler 後的 CSS 不得有超過兩層階層
.product {
&__item {
&--selected {}
}
}
上面的 SASS 寫法這樣其實也才一層而已哦,因為 compiler 出來之後是
.product {}
.product__item {}
.product__item--selected {}
適當的使用 >
.list {
&__item > a {}
}
這樣寫只會在 list__item
下一階層的第一個 a tag 會有效果而已,如果在這底下有兩個 a tag ,第二個會失效,這是特別要注意的點。
不要使用 Tag selector
BEM是不允許用 Tag selector 的
.menu li
能搞定的事情需要每個 li 都寫 .menu-item
優點: 就是避免 li 裡的 li 受影響 舉個例子,商品詳情頁是允許商家自定義標籤的,那麼商家展示區域標籤的祖先元素一旦用標籤選擇器定義了樣式,子子孫孫都要背負.
所以十分贊同在無法百分百確定不會嵌套同樣標籤的情況下不用 Tag selector
BEM 解決問題
組件之間的完全解耦,不會造成命名空間的污染,如: .mod-xxx ul li
的寫法帶來的潛在的嵌套風險。
性能
BEM 命名會使得 Class 類名變長,但經過 gzip 壓縮後這個帶寬開銷可以忽略不計
延伸閱讀 - 常用的CSS命名規則
- 頭:header
- 內容:content/container
- 尾:footer
- 導航:nav
- 側欄:sidebar
- 欄目:column
- 頁面外圍控制整體佈局寬度:wrapper
- 左右中:left right center
- 登錄條:loginbar
- 標誌:logo
- 廣告:banner
- 頁面主體:main
- 熱點:hot
- 新聞:news
- 下載:download
- 子導航:subnav
- 菜單:menu
- 子菜單:submenu
- 搜索:search
- 友情鏈接:friendlink
- 頁腳:footer
- 版權:copyright
- 滾動:scroll
- 內容:content
- 標籤:tags
- 文章列表:list
- 提示信息:msg
- 小技巧:tips
- 欄目標題:title
- 加入:joinus
- 指南:guide
- 服務:service
- 註冊:regsiter
- 狀態:status
- 投票:vote
- 合作夥伴:partner
注釋的寫法:
/* Header */
內容區
/* End Header */
Id的命名:
頁面結構
- 容器: container
- 頁頭:header
- 內容:content/container
- 頁面主體:main
- 頁尾:footer
- 導航:nav
- 側欄:sidebar
- 欄目:column
- 頁面外圍控制整體佈局寬度:wrapper
- 左右中:left right center
導航
- 導航:nav
- 主導航:mainnav
- 子導航:subnav
- 頂導航:topnav
- 邊導航:sidebar
- 左導航:leftsidebar
- 右導航:rightsidebar
- 菜單:menu
- 子菜單:submenu
- 標題: title
- 摘要: summary
功能
- 標誌:logo
- 廣告:banner
- 登陸:login
- 登錄條:loginbar
- 註冊:register
- 搜索:search
- 功能區:shop
- 標題:title
- 加入:joinus
- 狀態:status
- 按鈕:btn
- 滾動:scroll
- 標籤頁:tab
- 文章列表:list
- 提示信息:msg
- 當前的: current
- 小技巧:tips
- 圖標: icon
- 注釋:note
- 指南:guild
- 服務:service
- 熱點:hot
- 新聞:news
- 下載:download
- 投票:vote
- 合作夥伴:partner
- 友情鏈接:link
- 版權:copyright
注意事項::
- 一律小寫;
- 盡量用英文;
- 盡量不縮寫,除非一看就明白的單詞。
CSS樣式表文件命名
- 主要的 master.css
- 模塊 module.css
- 基本共用 base.css
- 佈局、版面 layout.css
- 主題 themes.css
- 專欄 columns.css
- 文字 font.css
- 表單 forms.css
- 補丁 mend.css
- 打印 print.css