紀錄一些 BEM 在使用時可能會碰到的問題。
對 Modifier 下的 Element 定義新的規則
假使我們有一個卡片組件如下:
1 | <article class="card"> |
現在我們想要定義一個新的 Modiefier, card--feature
,會長這樣子。
除了 card--feature
的背景顏色會改變之外, 其下的 card__title
, card__text
, card__button
也都要做修改,這種時候該怎麼寫才好?
有些人會這樣子寫:
1 | .card { |
但如果今天要改 class 名稱的時候,要修改的地方就會變很多。
所以建議你可以這樣子寫:
1 | .card { |
這樣子要改 class 名稱時,只要改最外層那個 card
就解決囉。
🚀 Codepen:點這裡
什麼時候不該寫成 BEM
當有一個 class 是可以獨立存在的時候
例如:
1 | .clearfix { |
雖然按照 BEM 的規則,你可以把它歸類成Modifier
。
但它其實是一個可以獨自存在的 class,而且可以用在網頁的各種地方。
所以比起寫成modifier
,把它歸類為一個單獨存在的 class,或許會更適合。
適合模組化的時機
假設你的 HTML 結構長這樣:
1 | <div class="content"> |
你可能會很直覺的寫成content__menu
這種結構。
但是如果你這樣子寫,意思就會是,menu
跟 content
區塊綁在一起。
那如果網頁中有其他的地方也會有選單的話呢?
你就沒辦法直接拿menu
這個模組來用了,因為它跟content
綁在一起了。
所以我們透過 BEM 來建立每個模組的時候要思考一件事:
「這個區塊有沒有可能會在網頁的其他地方出現」
所以回到上面的例子。
比起讓menu
作為content
下的Element
,menu
更適合當作是一個Block
,
這樣子menu
會成為一個模組,也就有更高的靈活性。
一個 Block 下最多只會連接一個 Element
這裡引用來自BEM by Example的一段敘述:
If your component has child elements several levels deep, don’t try to represent each level in the class name. BEM is not intended to communicate structural depth. A BEM class name representing a child element in the component should only include the base/block name and the one element name.
意思是說,假使一個 component 下有多個層級的子元素,我們也不必在 BEM 把每一層的結構寫出來,譬如說:
1 | <figure class="photo"> |
所以一個Block
下最多只會寫一層Element
:
1 | <figure class="photo"> |
即便你沒有把每一個層級都寫出來,也能夠看出img
, caption
, quote
都是photo
這個 component 下的元素。
所以只要掌握住一個原則:這個元素是哪個 component 下的元素,就能寫出簡潔清楚的 class 名稱。
有些元素不需要綁在 Block 上
拿我在Frontend Mentor挑戰中的header
部分來舉例:
1 | <header class="header"> |
slogan
跟arrow
這兩個元素其實都能獨自存在,並沒有一定要綁在header
這個Block
上(除非你把整個header
當成是一個 component),所以就不建議這樣子寫:
1 | <header class="header"> |
這種情況大多會發生在文字的部分,所以這種時候就建議寫一個方便識別的 class 就好,不用一定要照著 BEM 的規則來命名。
參考資料
BEM by Example
竹白記事本-BEM,CSS 設計模式
IT 人-[譯] CSS 使用 BEM 命名規範的五大理由