BEM實戰之扒一扒淘票票頁面

TeanLee發表於2019-03-03

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…

相關文章