所有的 CSS 設計模式都是為了維持可讀性、好維護、易擴充這幾個目標,今天就來談談 BEM 設計模式,並搭配 Sass 中的 SCSS 來介紹,並探討在各種情境下該如何使用 BEM。
先說說 BEM 有哪些好處:
1. 從 Class 命名可以馬上看出結構之間的相依性
2. 避免 Sass 過多嵌套的問題(一般來說最多是三層)
3. 適合任何大小專案
初期使用應該會覺得命名很痛苦,或是覺得命名很長長長,後面這個問題已經可以透過 SCSS 引用父選擇器&
解決,前者的話就只能多寫幾次熟悉了。接下來正式介紹 BEM。
__
將區塊和元素名稱連接,例如 .banner__title
--
與區塊或元素名稱連接,例如 .banner__title--big
或是 .title--primary
範例如下,可以看到區塊為 banner,並有三個元素從屬於 banner 區塊:
<div class="banner">
<h2 class="banner__title">標題</div>
<h3 class="banner__subtitle">子標題</div>
<div class="banner__img"><img src="banner.jpg" alt="banner" /></div>
</div>
-
。關於最後一點,筆者為了可讀性,較傾向使用小駝峰,畢竟 BEM 裡面有較多的 --
和 __
,假如又額外加入了一些共通樣式的 class,例如命名為 .text-center,乍看還需要分辨裡面的 -
是拿來連接單詞,還是用來描述 class 用途。
以功能性來命名,例如 .navbar, .card 等等,且具有唯一性,一般不會寫入樣式,Block 裡面可以再包其他 block,可以存在於頁面任何一個地方。
不能獨立於區塊之外,以目的來命名。
可以針對區塊或是元素做樣式微調,Modifier 絕對不能單獨存在,他必須和相關的區塊或是元素一起出現,經常用於調整大小、顏色、狀態等等。
<div class="banner banner--small">
<h2 class="banner__title banner__title--big">標題</div>
<h3 class="banner__subtitle">標題</div>
<div class="banner__img"><img src="banner.jpg" alt="banner" /></div>
</div>
假如樣式可以單獨存在,就應該直接獨立成一個 class ,供網頁中所有元素視情況使用,例如 .hidden 就可能是專門用來將某個元素隱藏,並不屬於任何一個區塊。
這篇文章中有提到 BEM 的 Modifier 不適合用在狀態變化,狀態變化舉例像是按鈕按下去之後會變換樣式,該文章作者建議可以使用 SMACSS 概念代替,例如使用 .is-closed
、.is-open
的命名。
我認為這個作法不只是為了簡潔、可讀性,也有可能是因為狀態變化經常需要和 JS 做搭配,如果名稱取得太長,會導致取得 DOM 元素時的語法也會跟著很長,從而影響 JS 易讀性降低。
建議 BEM 只能一個區塊對應一個元素,也就是不允許使用兩組下底線來標示從屬關係,例如 .card__body__title
就打破了這個規則,在這邊提供兩個寫法參考:
寫法一:使用減號連接
<ul>
<li class="card">
<div class="card__head">
<h2 class="card__head-title"></h2>
</div>
<div class="card__body">
<h3 class="card__body-title"></h3>
</div>
</li>
</ul>
card{
&__head{
...
&-title{
...
}
}
}
寫法二:如果結構比較簡單,只有單一、但很多層,也可以只寫和最大區塊的從屬關係
<nav class="nav">
<ul class="nav__list">
<li class="nav__item">
<a href="nav__link"></a>
</li>
</ul>
</nav>
.nav{
&__list{
...
}
&__item{
...
}
}
建議能拆成一個區塊的就拆出來,最後再把它們組裝起來,就能避免結構過多的問題,寫 BEM 時很重要的一點是結構深度要拿捏好,不要寫得太深入。
如果某個區塊在另一個區塊裡面時,樣式有些微不同,可以使用 Modifier 寫法避免搞混,範例中的 .nav--inside-footer
就是專門為 footer 裡的導覽列區塊特別設定的樣式。
<footer>
<ul class="nav nav--inside-footer">
<li class="nav__item">
<a href="#" class="nav__link"></a>
</li>
<li class="nav__item">
<a href="#" class="nav__link"></a>
</li>
</ul>
</footer>
有時不用太過遵守 BEM 規則,網頁中並不是所有內容都會用上 BEM,某些常用設定可以直接成為一個單純的 Class,例如 .clearfix
;或是透過一些標記,清楚知道這是一個全域的樣式設定,例如 .g-clearfix
,在前面加入的 g 代表 global,表示這是一個全局樣式。
有關 BEM 設計模式的分享就到這裡,若有錯誤歡迎指正,感謝看完這篇的大家。