[規範] CSS BEM

啊就是我發表於2020-01-16

為什麼有BEM

開發一個大型專案的時候,經常會出現如下的css編寫效果:

  .container .form .input  .warpper .icon {
        /*需要的css*/
    }  

  .container .form .text  {
       /*需要的css*/
  }

 .page .warpper .layout .content{
       /*需要的css*/
  }
複製程式碼

這樣的css編寫效果就是傳統的名稱空間的方式寫css,它很好得解決了編寫單純全域性css互相影響的問題,但是另外一方面它也引申出了一些問題:

1、維護css的時候,只看HTML,我們無法知道當前css的作用範圍,css的表現不夠一目瞭然。

2、 如果要覆蓋css的樣式,可能就需要利用css的優先順序的規則去覆蓋原有的css,這樣就會導致css優先順序競爭。

3、css編寫的時候複用性不高,當存在多個樣式一致的時候,我們可能會選擇減少名稱空間的方式來提升當前css的作用範圍,但是可能會導致css樣式衝突的問題。
複製程式碼

所以BEM等解決方案就孕育而生。

BEM命名約定

使用 BEM 命名規範,理論上講,每行 css 程式碼都只有一個選擇器。

BEM代表 “塊(block),元素(element),修飾符(modifier)”,我們常用這三個實體開發元件。

在選擇器中,由以下三種符號來表示擴充套件的關係:

-   中劃線 :僅作為連字元使用,表示某個塊或者某個子元素的多單詞之間的連線記號。

__  雙下劃線:雙下劃線用來連線塊和塊的子元素

_   單下劃線:單下劃線用來描述一個塊或者塊的子元素的一種狀態

ype-block__element_modifier

複製程式碼

塊(block)

一個塊是設計或佈局的一部分,它有具體且唯一地意義 ,要麼是語義上的要麼是視覺上的。

在大多數情況下,任何獨立的頁面元素(或複雜或簡單)都可以被視作一個塊。它的HTML容器會有一個唯一的CSS類名,也就是這個塊的名字。

針對塊的CSS類名會加一些字首( ui-),這些字首在CSS中有類似 名稱空間 的作用。 一個塊的正式(實際上是半正式的)定義有下面三個基本原則:

  • CSS中只能使用類名(不能是ID)。
  • 每一個塊名應該有一個名稱空間(字首)
  • 每一條CSS規則必須屬於一個塊。

例如:一個自定義列表 .list 是一個塊,通常自定義列表是算在 mod 類別的,在這種情況下,一個 list 列表的block寫法應該為:

.list   
複製程式碼

元素(element)

塊中的子元素是塊的子元素,並且子元素的子元素在 bem 裡也被認為是塊的直接子元素 。一個塊中元素的類名必須用父級塊的名稱作為字首。

.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{}
}
複製程式碼

對應的HEML結構如下:

<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>
複製程式碼

元件之間的完全解耦,不會造成名稱空間的汙染,如:.mod-xxx ul li 的寫法帶來的潛在的巢狀風險。BEM 命名會使得 Class 類名變長,但經過 gzip 壓縮後這個頻寬開銷可以忽略不計

參考文章

1、github.com/Tencent/tmt… 【BEM規範】

2、www.jianshu.com/p/5e018c7f0… 【BEM規範入門】

相關文章