【CSS系列】命名千萬條,BEM第一條

一燈發表於2019-04-26

前言

  沒有太重視“命名”這個似乎不在技術範疇之內的東西,隨著專案更新迭代變得龐大,維護起來欲哭無淚。尤其是在CSS中,一個高效的命名規範到底有多重要?

  • 程式碼結構更加清晰有意義
  • 維護變得簡單
  • 同事看程式碼的時候不罵街了

  之前看到過一種醜醜的命名("__"和"--")不以為然,這正是本文探討的主題——BEM命名規範。

1. BEM簡介

  BEM(Block Element Modifier)是由Yandex(俄羅斯的網路服務門戶之一)團隊提出的一種前端命名規範,這裡講的BEM風格是經過改良的(沒有具體閱讀過相關文章,不探討有關如何改良的細節):

  • Block:塊
  • Element:元素——塊的組成部分
  • Modifier:修飾符——表示一種形態/狀態
.block {}
.block__element {}
.block--modifier
複製程式碼

  舉一個很好理解的例子:

#Block
人__手          #Element
人__手--小手      #Modifier
人__手--大手      #Modifier
人__腳          #Element

人--男人        #Modifier
人--男人__手      #Element
人--男人__腳      #Element

人--女人        #Modifier
人--女人__手      #Element
人--女人__腳      #Element
複製程式碼

2. BEM命名 vs 傳統命名

  好與不好,程式碼為證:

2.1 BEM命名

<!-- app.vue -->
<aside class="aside">
  <!-- 顯示/隱藏側邊欄 -->
  <img :class="['aside__toggle--show', {'aside__toggle--hide': isHide}]" />
  <ul class="aside__menu">
    <li class="aside__menu__item">首頁</li>
  </ul>
</aside>
複製程式碼
/*css*/
.aside {}
.aside__toggle--show {}
.aside__toggle--hide {}
.aside__menu {}
.aside__menu__item {}
複製程式碼
/*scss或less*/
.aside {
  &__toggle {
    &--show {}
    &--hide {}
  }

  &__menu {
    &__item {}
  }
}
複製程式碼

2.2 傳統命名

<!-- app.vue -->
<aside class="aside">
  <!-- 顯示/隱藏側邊欄 -->
  <img :class="['toggle', {'hide': isHide}]" />
  <ul class="menu">
    <li class="item">首頁</li>
  </ul>
</aside>
複製程式碼
.aside {}
.toggle {}
.menu {}
.item {}
複製程式碼

  當然也有一些針對傳統命名的優化,儘管看起來清晰很多,但意圖的表達仍然有些不明確

<!-- app.vue -->
<aside class="aside">
  <!-- 顯示/隱藏側邊欄 -->
  <img :class="['aside-toggle-show', {'aside-toggle-hide': isHide}]" />
  <ul class="aside-menu">
    <li class="aside-menu-item">首頁</li>
  </ul>
</aside>
複製程式碼
/*css*/
.aside {}
.aside-toggle-show {}
.aside-toggle-hide {}
.aside-menu {}
.aside-menu-item {}
複製程式碼
/*scss或less*/
.aside {
  &-toggle {
    &-show {}
    &-hide {}
  }
  &-menu {
    &-item {}
  }
}
複製程式碼

  通過對比可以看到,BEM命名使得程式碼結構清晰多了,並且能把程式碼的意圖表達得很明確。

3. 正確地使用BEM

  舉一個例子,你的手裡拿著一本書,但你不能說這本書是人的一部分。這就好比在程式碼中,有一個元素剛好某個塊中,但它本身並不屬於這個塊,按照BEM原則,此元素的命名不該包含進去:

<nav class="nav">
  <ul class="nav__menu">
    <li class="nav__menu__item">首頁</li>
  </ul>
  <!-- 顯示使用者名稱 -->
  <span class="username">XXX 你好!</span>
</nav>
複製程式碼

後記

  對於BEM命名規範本人還在實踐當中,也還存在一些疑問,例如在塊巢狀比較深時是否造成html程式碼冗長?待實踐一段時間有了新的想法再分享出來,大家有更好的命名方案歡迎在下方評論中分享。

  感謝你的閱讀!

相關文章