避免以視覺效果來命名類
盡量避免以類的視覺效果來命名:如.half
。因?yàn)槿绻褂庙憫?yīng)式布局,你的頁面會(huì)有多種布局來適應(yīng)多種顯示設(shè)備的需求讹蘑。一個(gè)元素可能要在臺(tái)式電腦上占據(jù)一半的寬度,但在移動(dòng)設(shè)備上你可能需要它占據(jù)全部的寬度。.half
的語義卻把這個(gè)元素的寬度定死了:
<div class="row">
<div class="column half">
<!-- Your Content -->
</div>
<div class="column half">
<!-- Your Content -->
</div>
</div>
如果這樣命名矿微,那么在移動(dòng)設(shè)備上你就需要用js刪除.half
類然后增加.full
類!
更好的方式是:類名僅描述類的功能尚揣,對(duì)于那些需要響應(yīng)式變化的類涌矢,我們使用媒體查詢,讓這個(gè)類在不同的環(huán)境中做出不同的布局表現(xiàn)快骗。
@media (min-width: 500px) {
類名 {
// 窄顯示設(shè)備下的樣式
}
}
@media (max-width: 500px) {
類名 {
// 寬顯示設(shè)備下的樣式
}
}
以類的功能來命名
類名應(yīng)該反映這個(gè)類的目的和類之間的層次結(jié)構(gòu)娜庇,而不是布局表現(xiàn)。
BEM 命名方式
BEM 是Block Element Modifier的縮寫方篮,它將一個(gè)類名分成這三個(gè)部分:模塊名秀、模塊元素、描述符藕溅。模塊規(guī)定整個(gè)組件的樣式匕得;模塊元素規(guī)定這個(gè)組件中子元素的樣式;描述符描述一種特殊的種類巾表,給模塊或模塊元素增加特別的樣式汁掠,以表示這個(gè)元素處于某種特別的狀態(tài)(比如說被選中的狀態(tài))。
使用BEM的類名清楚地展示了這個(gè)類的作用和層次結(jié)構(gòu)關(guān)系集币,并且有效避免了類名重復(fù)導(dǎo)致樣式覆蓋考阱。
BEM的寫法
使用__
連接模塊與模塊元素,使用--
來連接描述符鞠苟,如果一個(gè)名字由多個(gè)單詞組成乞榨,用單詞分隔符-
來分割。
// Block (Highest level)
.block {...}
// Element (Descendent of block)
.block__element {...}
// Modifier (Different state or version)
.block--modifier {...}
.block__element--modifier {...}
BEM例子
.person {}
.person__hand {}
.person--female {}
.person--female__hand {}
.person__hand--left {}
看到這個(gè)樣式表偶妖,我們馬上可以知道
-
person
就是整個(gè)部件姜凄; -
person__hand
描述person
的手(元素); -
person--female
描述person
中的女性(一個(gè)種類)趾访; -
person--female__hand
描述person--female
的手(元素)态秧; -
person__hand--left
描述person__hand
的一個(gè)種類:左手。
如果我們不使用BEM:
.person {}
.hand {}
.female {}
.female-hand {}
.left-hand {}
- 類與類之間的結(jié)構(gòu)不清晰(比如扼鞋,female到底是放在person的子標(biāo)簽中申鱼,還是放在同一個(gè)標(biāo)簽中愤诱?如果使用BEM,帶描述符的類與不帶描述符的類就一定放在同一個(gè)標(biāo)簽中捐友,見下面的例子)
- 類名容易重復(fù)(比如female可以指不同的動(dòng)物淫半,如果出現(xiàn)了重名、樣式覆蓋匣砖,會(huì)導(dǎo)致動(dòng)物的樣式應(yīng)用到人身上?瓶浴)
另一個(gè)例子:
<div class="shopping-cart">
<div class="shopping-cart__item">
<!-- Your Content -->
</div>
<div class="shopping-cart__item shopping-cart__item--selected">
<!-- Your Content -->
</div>
</div>
以上例子描述了一個(gè)購(gòu)物車組件的組成:
shopping-cart
規(guī)定了購(gòu)物車組件的總體樣式;組件中有元素shopping-cart__item
猴鲫,規(guī)定了購(gòu)物車中的商品條目的樣式对人;shopping-cart__item--selected
則表示這是一個(gè)特別的商品條目(被用戶選中的條目),我們可以給它添加特別的樣式拂共,比如紅色的邊框牺弄。
用了這種方式,我們看到類名就可以知道它規(guī)定了誰的樣式宜狐,并且類與類之間的關(guān)系也清晰了势告。
再看一個(gè)例子:搜索欄組件
反例:
<form class="site-search full">
<input type="text" class="field">
<input type="Submit" value ="Search" class="button">
</form>
使用BEM以后:
<form class="site-search site-search--full">
<input type="text" class="site-search__field">
<input type="Submit" value ="Search" class="site-search__button">
</form>
這里的
site-search--full
其實(shí)犯了我們開始說的錯(cuò)誤:用視覺效果來給類命名,這里應(yīng)該使用媒體查詢而不是用一個(gè)類來讓搜索欄占滿寬度抚恒。這個(gè)例子僅用來學(xué)習(xí)使用BEM咱台。
什么時(shí)候不必使用BEM
- 有一些樣式是在任何組件中都通用的:
.caps { text-transform: uppercase; } // 字母大寫顯示
- 有一些元素只是碰巧在這個(gè)組件中,與這個(gè)組件沒有什么必然的聯(lián)系柑爸,這個(gè)元素可以出現(xiàn)在很多其他的組件吵护,比如:
我們只需要定義一次網(wǎng)站logo的樣式:
.site-logo {}
網(wǎng)站logo可以放在網(wǎng)站的header盒音,footer表鳍,任何地方,他不應(yīng)該作為某一個(gè)組件的子元素:
.header {}
.header__logo {}
logo和header沒有必然聯(lián)系祥诽,他只是恰好出現(xiàn)在了header中譬圣,我們完全可以使用之前定義的.site-logo
。假如我們還要在footer中假如logo雄坪,難道我們還要定義一個(gè)footer__logo
嗎厘熟?這太多余了!
因此我們?cè)谑褂肂EM的時(shí)候要考慮清楚:這個(gè)元素是這個(gè)模塊的組成部分嗎维哈?還是說這個(gè)元素只是恰好出現(xiàn)在這個(gè)模塊中绳姨?如果是后者,不必使用BEM阔挠。
參考文章:
http://adamkaplan.me/blog/grid-retrospective
https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
補(bǔ)充:對(duì)照真實(shí)的項(xiàng)目來理解
如果沒有項(xiàng)目的體驗(yàn)飘庄,確實(shí)很難理解BEM的意義。BEM其實(shí)就是將類名分成三個(gè)部分來描述這個(gè)類的作用购撼。微信的樣式庫(kù)也是這么做的跪削,可以對(duì)照看看:https://github.com/weui/weui/blob/master/dist/style/weui.css
只用看其中和weui-cell
有關(guān)的類名就可以了谴仙。注意微信的樣式庫(kù)對(duì)連接符的使用和我這篇文章講的有點(diǎn)不一樣,一個(gè)下劃線_
后面是描述符碾盐,兩個(gè)下劃線__
后面的是元素晃跺。
感興趣的話還可以看看他們的DEMO,是如何使用的毫玖。
后續(xù)我會(huì)寫更多關(guān)于響應(yīng)式布局的內(nèi)容掀虎。