CSS 命名規範

BEM

命名規範要解決的問題

// 無意義的命名
.block1 {
    text-align: center;
    background: red;
}

// 如果每個頁面都有 block2,但卻有不同的樣式?
.block2 {
    text-align: center;
    background: blue;
}


// 充滿惡意的寫法
.text-center {
    text-align: left;
}

BEM 組成

  • 區塊 (Block)
  • 元素 (Element)
  • 修飾符 (modifier)

BEM 規範簡述

BEM 規範簡述

 區塊(Block)

多元素組合而成的元件

BEM 規範簡述

BEM 規範簡述

 元件 (Element)

組成 Block 的獨立元素

原則上是只有一個功能不可拆分的元素

Element 以兩個 _ 符號作為連接

BEM 規範簡述

 元件 (Element)

.stick-man__head {} 

.stick-man__arms {} 

.stick-man__feet {} 

比方說,這個火柴人有:

  • 一個頭部( head )
  • 兩隻手臂( arms )
  • 雙腳( feet )

Element 以兩個 _ 符號作為連接

BEM 規範簡述

修飾符 (Modifiers)

如同字面的意思

修飾符可直接

依附在 Block 或是 Element 上

Modifiers 以 -- 符號作為連接

BEM 規範簡述

修飾符 (Modifiers)

.stick-man--blue { } 

.stick-man--red { }

假設長得一模一樣的火柴人

紅色 (red) 與 藍色 (blue)

Modifiers 以 -- 符號作為連接

BEM 規範簡述

修飾符 (Modifiers)

.stick-man--blue { } 

.stick-man--red { }

假設長得一模一樣的火柴人

紅色 (red) 與 藍色 (blue)

Modifiers 以 -- 符號作為連接

BEM 規範簡述

修飾符 (Modifiers)

.stick-man__head--small { } 

.stick-man__head--big { }

假設長得一模一樣的火柴人

頭小 (small) 與 頭大 (big)

Modifiers 以 -- 符號作為連接

以上就是 BEM

基本用法了

BEM 與 命名空間

可以直接在 Block 加上命名空間

  1.  Layouts 佈局

  2.  Objects 物件

  3.  Components 組件

  4.  Utility 實用工具

  5.  States 狀態

  6.  JavaScript hooks

BEM 與 命名空間

Layouts 佈局

例如 l-header l-wrap l-footer

Layout 用來定義這些「大架構」

.l-wrap {
  width: 100%;
  padding-left: 1em;
  padding-right: 1em;
  margin-right: auto;
  margin-left: auto;
}

l-(Layout)

BEM 與 命名空間

Objects 物件

例如 o-button

依據個人習慣可以選擇下列的方式進行命名

 

1. o-(Objects)物件

2. e-(Element)元素

3. u-(Unit)零件

網頁中的最小構建塊

裡面不能包含其他物件或組件

BEM 與 命名空間

Components 組件

依據個人習慣可以選擇下列的方式進行命名

 

1. c- (Component)

2. m- (Module)

組件 (Component) 裡面

可以包含很多 物件 (object)

BEM 與 命名空間

Utility 工具

Utility 工具

獨立 且 可以直接

附加在任何 Component 與 Object 的樣式

依據個人習慣可以選擇下列的方式進行命名

 

1. u-(Utility)

2. h-(Helpers)

3. f-(Fuctions)

例如: u-mt 、 u-mt--large

BEM 與 命名空間

States 狀態

狀態類 (States) 表示物件/組件的當前狀態,通常會搭配 JavaScript 做使用

依據個人習慣可以選擇下列的方式進行命名

 

1. is-

2. has-

例如: is-active、has-loaded

BEM 與 命名空間

JavaScript hooks

js- 表示物件或組件是否需要用到 JavaScript

碰見問題:

在用 jQuery 可以常常看到這樣的寫法:

$('.nav–main a')

一旦 CSS 發生重構,JavaScript 代碼也將變得難以維護,分不清哪些代碼會受到影響

BEM 與 命名空間

JavaScript hooks

js- 表示物件或組件是否需要用到 JavaScript

<li class="nav__item js-nav__item"></li>

使用 js- 來表示

這樣看到 js-nav__item 馬上就可以知道 nav__item 需要 JavaScript 才能正常工作

BEM 與 SASS

利用 Sass 的 & 父連接詞與巢狀你可以很輕鬆的寫出 BEM 命名結構

<nav class="c-menu c-menu--lg">
  <ul class="c-menu__list">
    <li class="c-menu__item">
      <a class="c-menu__link"></a>
    </li>
    <li class="c-menu__item">
      <a class="c-menu__link"></a>
    </li>
  </ul>
</nav>

BEM 與 SASS

.c- {
  /* style */
  &menu {
    ...
    &__list {
      /* style */
    }
    &__item {
      /* style */
    }
    &__link {
      /* style */
    }
    
    &--lg {
      /* style */
    }
    &--lg &__item {
      /* style */
    }
    &--lg &__link {
      /* style */
    }
  }
}

BEM 會遇到的問題

如何處理 Element 的子元素

當你需要選擇一個嵌套超過兩層的元素

也就是 element 裡面還有 element

<nav class="c-menu">
  <ul class="c-menu__list">
    <li class="c-menu__list__item">
      <a class="c-menu__list__item__link"></a>
    </li>
    <li class="c-menu__list__item">
      <a class="c-menu__list__item__link"></a>
    </li>
  </ul>
</nav>

有人可能會這樣寫:

這種方式會很快就會脫離控制

並且一個組件嵌套的越深,可讀性就會變得越差

如何處理 Element 的子元素

<nav class="c-menu">
  <ul class="c-menu__list">
    <li class="c-menu__item">
      <a class="c-menu__link"></a>
    </li>
    <li class="c-menu__item">
      <a class="c-menu__link"></a>
    </li>
  </ul>
</nav>

回歸基本 B__E--M 的原則,的寫法

  • 命名只是用來幫助你識別子元素和頂層組件塊的關係
  • 沒必要在類名中呈現 HTML 的結構

另外這也表示所有的子元素都僅僅會被 .c-menu 影響,link 不會綁死在 item 下,也可以新增在 list 外

組件的樣式微調

<nav class="c-menu">
  <button class="o-button o-button--primary">Click me!</button>
</nav>

當 o-button 這個 object 的類別

在 c-menu 要額外加點 圓角 的樣式時,要如何處理 ?

只要加一個 c-menu__c-button 的類別名稱在 o-button 之後

按照 CSS 的載入順序,進行附加的樣式就可以了

<nav class="c-menu">
  <button class="o-button c-menu__o-button">Click me!</button>
</nav>

這是官方提供的 Mixed 的方法

組件會不會最終有

無數個 class 名稱

但這並非個問題,因為這意味著代碼更具有可讀性,你更能清楚的知道它是用來實現什麼的

<button class="c-button c-button--primary is-active">
    Click me!
</button>

如下列的例子:

第一眼看到的時候覺得語法不是最簡潔的,但是非常清晰

參考資料

CSS 設計模式 BEM

By ZHI-WEI HUANG

CSS 設計模式 BEM

  • 67