命名約定
若是使用 BEM 實(shí)體,就需要了解它的命名規(guī)則。
命名約定的理念就是使得 CSS 選擇器的命名盡可能的直觀,盡可能的簡(jiǎn)單。這將使得開(kāi)發(fā)和調(diào)試更容易,也解決了 web 開(kāi)發(fā)者所面臨的一些問(wèn)題。
現(xiàn)在,我們有一個(gè)名字為 menuitemvisible
的 CSS 選擇器。然而,對(duì)直觀來(lái)看,對(duì)這樣一個(gè)選擇器名稱,我們不能快速地從中確定 BEM 實(shí)體的類型。
讓我們添加一個(gè)分隔符:
menu-item-visible
或者 menuItemVisible
像上面這樣寫(xiě),選擇器的名稱被清晰地分割成不同邏輯部分。我們可以假定 menu
是一個(gè)模塊,item
是一個(gè)元素,visible
是一個(gè)修飾符。然而,真實(shí)的例子通常是復(fù)雜的,并沒(méi)有如此的簡(jiǎn)單,這正是 BEM 命名約定的用武之處。
BEM 方法論為創(chuàng)建命名規(guī)則提供了一種思路,并且遵循這種思路來(lái)規(guī)范 CSS 選擇器命名約定。然而,在 web開(kāi)發(fā)的世界中也有許多基于 BEM 原則的替代方案。
CSS 選擇器命名約定
- 使用數(shù)字和小寫(xiě)的拉丁文字符書(shū)寫(xiě) BEM 實(shí)體名稱。
- 名字中的每一個(gè)單詞使用連字符(-)分隔開(kāi)來(lái)。
- 關(guān)于模塊,元素和修飾符的名字信息存儲(chǔ)在 CSS 類中。
命名規(guī)則:
- 模塊
- 元素
- 修飾符
模塊名稱
一個(gè)模塊遵循 block-name
的格式,相當(dāng)于為元素和修飾符定義了一個(gè)命名空間。
有時(shí),模塊名稱可以添加不同的前綴。
例子
menu
lang-switcher
HTML
<div class="menu">...</div>
CSS
.menu {color: red;}
元素名稱
由模塊的名稱定義的命名空間決定了一個(gè)元素屬于這個(gè)模塊。一個(gè)元素的名稱使用雙下劃線(__)與模塊名稱相分隔。
使用如下的方式創(chuàng)建一個(gè)元素的全名:
block-name__elem-anem
如果一個(gè)模塊擁有幾個(gè)完全相同的元素,就像菜單項(xiàng)這個(gè)例子中,所有相同的元素將有相同的名字 menu__item
。
重要提示!BEM 方法論中,在元素內(nèi)部嵌套元素是不被推薦的(譯者注:意思就是使用這樣的命名block__elem1__elem2
是不被推薦的。)
例子
menu_item
lang-switcher__lang-icon
HTML
<div class="menu">...<span class="menu_item"></span></div>
CSS
.menu__item { color: red; }
修飾符名稱
由模塊或者元素的名稱定義的命名空間,決定了一個(gè)修飾符屬于這個(gè)模塊或元素。一個(gè)修飾的名字使用一個(gè)單下劃線與前面的模塊或元素名稱相分隔。
使用下面的方式創(chuàng)建一個(gè)修飾符的全名:
- Boolean類型的修飾符 ——
owner-name_mod-name
。 - key-value 類型的修飾符 ——
owner-name_mod-name_mod-val
。
重要提示!在 BEM 方法論中,一個(gè)修飾符不能再它所屬的上下文環(huán)境之外被使用
模塊修飾符
-
Boolean 類型的修飾符。這種類型的修飾符的值不需要明確指定。使用下面的方式創(chuàng)建這種修飾符的全名:
block-name_mod-name
例子
menu_hidden
-
key-value類型的修飾符。這種類型的修飾符使用單下劃線(_)將其值與修飾符的名稱相分隔。使用
block-name_mod-name_mod-val
的方式創(chuàng)建一個(gè)修飾符的全名。
例子
menu_theme_morning-forest
HTML
<div class="menu menu_hidden">...</div>
<div class="menu menu_theme_morning-forest">...</div>
<!-- 不正確的 -->
<div class="menu_hidden">...</div>
<!-- 這里丟失了有修飾符影響的模塊的名稱 -->
CSS
.menu_hidden { display: none; }
.menu_theme_morning-forest {color: green;}
元素修飾符
-
Boolean 類型的修飾符。這種類型的修飾符的值不需要明確指定。使用下面的方式創(chuàng)建這種修飾符的全名:
block-name__elem-name_mod-name
.
例子
menu__item_visible
- Key-value 類型的修飾符。
例子
menu__item_type_radio
HTML
<div class="menu"> ... <span class="menu__item menu__item_visible menu__item_type_radio"></span> </div>
CSS
.menu__item_type_radio { color: blue; }
使用命名約定的一個(gè)例子
使用 HTML 和 CSS 實(shí)現(xiàn)的一個(gè)認(rèn)證表單
HTML
<form class="form form_login form_theme_forest">
<input class="form__input">
<input class="form__submit form__submit_disabled">
</form>
CSS
.form {}
.form_theme_forest {}
.form_login {}
.form__input {}
.form__submit {}
.form__submit_disabled {}
可供選擇的命名方案
這里有一些可供選擇的基于 BEM 命名約定的方案。
Two Dashes style(雙連字符風(fēng)格)
block-name__elem-name--mod-name
- 名字全部使用小寫(xiě)。
- BEM 實(shí)體的名稱中的每一個(gè)單詞使用一個(gè)連字符分隔。
- 使用雙下劃線(__)將元素的名稱和模塊的名稱分離開(kāi)。
- 使用雙連字符(--)分隔 Boolean 類型的修飾符。
- 不使用 key-value 類型的修飾符
重要提示!在注釋中,雙連字符被視為注釋的一部分,因此在文檔驗(yàn)證時(shí),雙破折號(hào)可能會(huì)引起錯(cuò)誤。HTML5 Specification
CamelCase style(駝峰命名風(fēng)格)
MyBlock__SomeElem_modName_modVla
這種風(fēng)格的命名方案的不同點(diǎn)在于,在 BEM 實(shí)體中分隔單詞時(shí)使用駝峰命名法代替了一個(gè)連字符(-)。
"Sans underscore" style(無(wú)下劃線風(fēng)格)
blockName-elemName--modName--modVal
- 名稱使用駝峰命名法書(shū)寫(xiě)。
- 元素名稱與模塊名稱使用一個(gè)連字符(-)分隔。
- 修飾符使用雙連字符(--)與模塊或元素分隔,
- 修飾符的名稱和值使用雙連字符(--)分隔。
重要提示!
在注釋中,雙連字符被視為注釋的一部分,因此在文檔驗(yàn)證時(shí),雙破折號(hào)可能會(huì)引起錯(cuò)誤。HTML5 Specification
No namespace style(無(wú)命名空間風(fēng)格)
_available
這種風(fēng)格的特征在于修飾符的前面沒(méi)有模塊或元素的名稱與其相連。這種方式限制了使用混合模式,這是由于并不能確定這個(gè)修飾符屬于哪個(gè)模塊或元素。
選擇哪一種風(fēng)格
BEM 方法論為 BEM 實(shí)體的命名提供了基本的原則。選擇哪一種命名方式取決于你項(xiàng)目的需求和你的個(gè)人喜好。使用方法論中提到的命名約定的一大優(yōu)勢(shì)在于具有現(xiàn)成的面向“經(jīng)典命名”的開(kāi)發(fā)工具。
除此之外,BEM 方法論不僅僅局限于在本文討論的 HTML 和 CSS 技術(shù),模塊,元素和修飾符的概念同樣適用于 JavaScript ,模板技術(shù)和 BEM 項(xiàng)目的文件結(jié)構(gòu)中。bem-naming工具使我們可以在所有可以使用到的實(shí)現(xiàn)技術(shù)中使用相同命名的 BEM 實(shí)體。
默認(rèn)情況下,bem-naming
工具的配置默認(rèn)為方法論中提到的命名約定,但是你可以添加你自己規(guī)則進(jìn)去。