CSS BEM 書寫規範
BEM命名約定
BEM 是由 Yandex 團隊提出的一種前端命名方法論。網上流傳的主要是兩個版本,一個是Yandex 原版BEM,還有一個是Nicolas Gallagher 修改版,這裏我們採用的是 Yandex 團隊原版的 BEM 規範。
使用 BEM 命名規範,理論上講,每行 css
代碼都只有一個選擇器。
BEM代表 “塊(block),元素(element),修飾符(modifier)”,我們常用這三個實體開發組件。
在選擇器中,由以下三種符號來表示擴展的關係:
- 中劃線 :僅作爲連字符使用,表示某個塊或者某個子元素的多單詞之間的連接記號。
__ 雙下劃線:雙下劃線用來連接塊和塊的子元素
_ 單下劃線:單下劃線用來描述一個塊或者塊的子元素的一種狀態
type-block__element_modifier
塊(block)
一個塊是設計或佈局的一部分,它有具體且唯一地意義 ,要麼是語義上的要麼是視覺上的。
在大多數情況下,任何獨立的頁面元素(或複雜或簡單)都可以被視作一個塊。它的HTML容器會有一個唯一的CSS類名,也就是這個塊的名字。
針對塊的CSS類名會加一些前綴( ui-
),這些前綴在CSS中有類似 命名空間 的作用。
一個塊的正式(實際上是半正式的)定義有下面三個基本原則:
- CSS中只能使用類名(不能是ID)。
- 每一個塊名應該有一個命名空間(前綴)
- 每一條CSS規則必須屬於一個塊。
例如:一個自定義列表 .list
是一個塊,通常自定義列表是算在 mod
類別的,在這種情況下,一個 list
列表的block寫法應該爲:
.list
元素(element)
塊中的子元素是塊的子元素,並且子元素的子元素在 bem
裏也被認爲是塊的直接子元素。一個塊中元素的類名必須用父級塊的名稱作爲前綴。
如上面的例子,li.item
是列表的一個子元素,
.list{}
.list .item{}
.list{}
.list__item{}
修飾符(modifier)
一個“修飾符”可以理解爲一個塊的特定狀態,標識着它持有一個特定的屬性。
用一個例子來解釋最好不過了。一個表示按鈕的塊默認有三個大小:小,中,大。爲了避免創建三個不同的塊,最好是在塊上加修飾符。這個修飾符應該有個名字(比如:size
)和值( small
,normal
或者 big
)。
如上面的例子中,表示一個選中的列表,和一個激活的列表項
.list{}
.list.select{}
.list .item{}
.list .item.active{}
.list{}
.list_select{}
.list__item{}
.list__item_active{}
關於風格
書寫原則
1. 原則上不會出現2層以上
選擇器嵌套
使用BEM
原則,用命名來解耦,所有類名都爲一層,增加效率和複用性
2. 兩層選擇器嵌套出現在.mod-xxx__item_current
子元素的情況,如下:
使用推薦的嵌套寫法
常規寫法:
.xxx{}
.xxx__item{}
.xxx__item_current{}
// 嵌套寫法
.xxx__item_current .mod-xxx__link{}
推薦:
.xxx{}
.xxx__item{}
.xxx__item_hightlight{}
.xxx__product-name{}
.xxx__link{}
.xxx__ming-zi-ke-yi-hen-chang{}
// 嵌套寫法
.xxx__item_current{
.xxx__link{}
}
對應的HTML結構如下:
<ul class="xxx">
<li class="xxx__item">第一項
<div class="xxx__product-name">我是名稱</div>
<span class="xxx__ming-zi-ke-yi-hen-chang">看類名</span>
<a href="#" class="xxx__link">我是link</a>
<li>
<li class="xxx__item xxx__item_current">第二項 且 當前選擇項
<div class="xxx__product-name">我是名稱</div>
<a href="#" class="xxx__item-link">我是link</a>
<li>
<li class="xxx__item xxx__item_hightlight">第三項 且 特殊高亮
<div class="xxx__product-name">我是名稱</div>
<a href="#" class="xxx__item-link">我是link</a>
<li>
</ul>
BEM 解決問題
組件之間的完全解耦,不會造成命名空間的污染,如:.mod-xxx ul li
的寫法帶來的潛在的嵌套風險。
性能
BEM 命名會使得 Class 類名變長,但經過 gzip 壓縮後這個帶寬開銷可以忽略不計
</div>
<div id="wiki-footer" class="mt-5 muted-link wiki-footer">
<a class="d-block p-3 muted-link text-center border border-dashed rounded-1" href="/BaiwangTradeshift/Frontend-Resources/wiki/_new?wiki%5Bname%5D=_Footer"><svg class="octicon octicon-plus mr-1" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 9H7v5H5V9H0V7h5V2h2v5h5v2z"></path></svg> Add a custom footer</a>
</div>
</div>