BEM解析
BEM是一套CSS國際命名規範,是一個非常有用的功能強大且簡單的命名約定,它能使前端程式碼更易讀,易於理解易於擴充套件。BEM是塊(block)、元素(element)、修飾符(modifier)的縮寫。
- B:Block是塊,一個獨立的元件,將所有東西都劃分成一個元件
- E:Element是塊中的子節點,為了表明子節點屬於哪個塊,寫法是 block__element
- M:Modifier宣告某個節點的修飾狀態
我們以一個搜尋框來簡單說明上述三個東西的用法:
這個搜尋框就可以看作一個塊Block,這個塊裡由兩個子節點,一個是輸入區域input,還有一個是查詢按鈕button。
對於這個塊的命名,按照BEM法則,我們可以寫成以下這樣:
<form class="site-search">
<input type="text" class="site-search__input">
<input type="button" class="site-search__button" value="search">
</form>複製程式碼
將整體的搜尋框命名為site-search作為一個模組,模組下的兩個子節點就在後面加上兩根下劃線,加上自己的名字 input 和 button,這樣的命名方式,即使我們沒有看到網頁內容,只看了CSS樣式名字,也能感受到頁面結構和頁面元素之間的關係。
如果要說明按鈕button是灰色的,我們還可以加上修飾的類名modifier,比如可以是site-search__button–gray。
上圖就說明能將某個元素進行模組化,裡面能夠包含多個元素,這樣的命名規範能夠更好的說明元素之間的關係。
為什麼要使用BEM方式命名
你是否遇到過寫CSS樣式名抓耳撓腮的時候?你是否遇到過團隊合作時看不清別人程式碼,只能無奈的說“這個CSS重寫一遍比修改老檔案快”?
BEM命名法則給我們帶來了以下的便利:
- BEM命名法則給我們提供了一個很好的模板,在命名中就能體現各個元素之間的關係,CSS的命名更加語義化,元素更易讀懂。
- 而且獨一無二的命名方式,使得程式碼能夠得到更好的複用,就不用在寫樣式名的時候小心翼翼,生怕和前後文的樣式名重名,導致元素元件的樣式被覆蓋。
- 剛接觸BEM命名方式可能會覺得一個元素的類名這麼冗長,比較難看,可就是這種冗長的命名,極大的減少了類名重複的可能性。
BEM官網說明這種命名規範最關鍵的特徵就是:
BEM的關鍵特徵就是塊的獨立性。按照CSS的建議,可以在網頁上的任何位置放置一個塊,並確保不會受到周圍環境的影響。而且,如果您最近需要將另一個塊巢狀到當前塊中,則它們的完全相容性將得到保證。換句話說,在維護Web應用程式時,您可以在整個頁面上移動塊,新增其他項並將其組合起來。
扒一扒淘票票介面
淘票票介面寫的挺美觀的,但是最近看了看淘票票的CSS命名方式,覺得稍有不妥。
比如淘票票最頂部的索引橫條。
以下是淘票票對於頂部導航欄的CSS命名,為了讓大家更好看清頁面結構,我對頁面元素進行了簡單的處理,以及新增了幾行註釋:
<div class="head-wrap" data-spm="header">
<div class="head-content center-wrap">
<!-- logo:淘票票logo的放置 -->
<h1 class="logo">
</h1>
<!-- cityWrap:有一欄顯示當前城市 -->
<div class="cityWrap M-cityWrap">
</div>
<!-- nav-wrap:幾個切換頁面的地方 -->
<div class="nav-wrap">
<ul class="nav">
<li class="J_NavItem current ">
<a href="#" target="_top">首頁</a>
</li>
</ul>
</div>
<!-- entrance-wrap:最右邊的兩個導骯 -->
<div class="entrance-wrap">
<ul class="entrance">
<li class="entrance-item">
<a class="phone" href="#" target="_blank">手機購買</a>
</li>
<li class="entrance-item">
<a class="service">客服諮詢</a>
</li>
</ul>
</div>
</div>
</div>複製程式碼
這裡存在兩個較為嚴重的問題:
1、頁面結構不清晰。從CSS的命名方式上來看,很難看得出上面這些類是放在一塊的,同一模組中的內容缺少聯絡。
2、CSS命名與頁面內容掛鉤,程式碼複用性低。觀察以上的命名方式,比如cityWrap、entrance、phone之類的,命名方式都和頁面內容掛鉤,這種命名方式缺點就是不能挪到其他地方進行復用。因為其他頁面可能沒有城市、入口、手機這些內容。或者,萬一頁面元素要進行更改,比如把城市(cityWrap)改成國家(country),為了保持CSS和頁面內容的統一性,就要更改所有的CSS樣式,給程式碼的維護增加了不小的困難。
我的更改建議是使用BEM命名法則,將頁面元素模組化.
整個導航欄作為一個模組,模組可以分為典型的三層:head、body、footer,分別存放logo、導航條內容、尾部的其他功能:
<!-- 整個導航欄堪稱一個模組Block,由三個子節點Element -->
<div class="head-wrap" data-spm="header">
<div class="head-wrap__hd">
<h1 class="head-wrap__logo">
</h1>
</div>
<div class="head-wrap__bd">
<div class="head-wrap__bd__title">南昌</div>
<div class="head-wrap__bd__content">
<ul class="head-wrap__bd__item">
<li class="head-wrap__bd__items">首頁</li>
</ul>
</div>
</div>
<div class="head-wrap__ft">
<ul class="head-wrap__ft__item">
<li class="head-wrap__ft__items"><a>手機購買</a></li>
</ul>
</div>
</div>複製程式碼
導航條看成一整個模組Block,該模組有三個子節點元素Elemet,經過這種命名方式,即使不看頁面元素,只看CSS元素的類名,是不是也能猜出大概結構來呢?而且不使用頁面的內容作為命名方式,這樣的話,以後有類似結構的頁面,也能直接複用這一套CSS樣式,同時,清晰的命名方式也讓頁面維護變得更為簡單。
Segmentfault 文章地址:segmentfault.com/a/119000001…