BEM 設計模式與各種使用情境

更新於 發佈於 閱讀時間約 8 分鐘

所有的 CSS 設計模式都是為了維持可讀性、好維護、易擴充這幾個目標,今天就來談談 BEM 設計模式,並搭配 Sass 中的 SCSS 來介紹,並探討在各種情境下該如何使用 BEM。

先說說 BEM 有哪些好處:

1. 從 Class 命名可以馬上看出結構之間的相依性

2. 避免 Sass 過多嵌套的問題(一般來說最多是三層)

3. 適合任何大小專案

初期使用應該會覺得命名很痛苦,或是覺得命名很長長長,後面這個問題已經可以透過 SCSS 引用父選擇器& 解決,前者的話就只能多寫幾次熟悉了。接下來正式介紹 BEM。

BEM 主要由三個概念組成

  • Block 區塊:限定了樣式的作用域,本身通常不會寫入樣式設定
  • Element 元素:需要綁定在區塊底下,使用兩個下底線 __ 將區塊和元素名稱連接,例如 .banner__title
  • Modifier 修飾器:用來修飾區塊或是元素的樣式,和 Element 一樣,不能獨立存在,需要使用兩個減號 -- 與區塊或元素名稱連接,例如 .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 選擇器
  • 不要過度模組化,需要拿捏模組的深度
  • 區塊和元素的命名有兩個單字以上時可使用小駝峰或 -

關於最後一點,筆者為了可讀性,較傾向使用小駝峰,畢竟 BEM 裡面有較多的 -- 和 __,假如又額外加入了一些共通樣式的 class,例如命名為 .text-center,乍看還需要分辨裡面的 - 是拿來連接單詞,還是用來描述 class 用途。

Block 區塊

以功能性來命名,例如 .navbar, .card 等等,且具有唯一性,一般不會寫入樣式,Block 裡面可以再包其他 block,可以存在於頁面任何一個地方。

Element 元素

不能獨立於區塊之外,以目的來命名。

Modifier 修飾器

可以針對區塊或是元素做樣式微調,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 就可能是專門用來將某個元素隱藏,並不屬於任何一個區塊。

Modifier 不適合用在狀態變化

這篇文章中有提到 BEM 的 Modifier 不適合用在狀態變化,狀態變化舉例像是按鈕按下去之後會變換樣式,該文章作者建議可以使用 SMACSS 概念代替,例如使用 .is-closed.is-open 的命名。

我認為這個作法不只是為了簡潔、可讀性,也有可能是因為狀態變化經常需要和 JS 做搭配,如果名稱取得太長,會導致取得 DOM 元素時的語法也會跟著很長,從而影響 JS 易讀性降低。

情境題

Q1. 只有兩層當然容易命名,那如果到第三層呢?

建議 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{
...
}
}

Q2. 如果真的結構有很多層、又很複雜,或是寫入了太多的 Modifier 導致易讀性降低怎麼辦?

建議能拆成一個區塊的就拆出來,最後再把它們組裝起來,就能避免結構過多的問題,寫 BEM 時很重要的一點是結構深度要拿捏好,不要寫得太深入。

Q3. 當兩個區塊混合時,該如何撰寫才不會覆蓋樣式或是造成混亂?

如果某個區塊在另一個區塊裡面時,樣式有些微不同,可以使用 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>

Q4. 如果我想針對一些頁面中的常見樣式做設定,它並不屬於任何一個結構,該如何撰寫?

有時不用太過遵守 BEM 規則,網頁中並不是所有內容都會用上 BEM,某些常用設定可以直接成為一個單純的 Class,例如 .clearfix;或是透過一些標記,清楚知道這是一個全域的樣式設定,例如 .g-clearfix,在前面加入的 g 代表 global,表示這是一個全局樣式。 

參考文章


有關 BEM 設計模式的分享就到這裡,若有錯誤歡迎指正,感謝看完這篇的大家。

留言
avatar-img
留言分享你的想法!
avatar-img
傑米的沙龍
7會員
30內容數
正在一點一滴學習程式,相信知識量總有一天會匯聚成大海,目前專門研究前端中。
傑米的沙龍的其他內容
2023/10/06
要改變表單元素的樣式其實相當麻煩,有些樣式還不能更改,這篇就來探討如何把它們改成喜歡的模樣吧。
Thumbnail
2023/10/06
要改變表單元素的樣式其實相當麻煩,有些樣式還不能更改,這篇就來探討如何把它們改成喜歡的模樣吧。
Thumbnail
2023/10/05
一個超簡單就能達到滾動視差的套件 - AOS
Thumbnail
2023/10/05
一個超簡單就能達到滾動視差的套件 - AOS
Thumbnail
2023/10/04
切版有許多眉角需要注意,來探討那些經常導致切版結果與設計稿產生落差的原因。 一、文字的高度本體是 line-height:🔍 文字所佔據的高度不是由font-size決定,而是line-hight。一開始練習切版時,都想著設定好字的尺寸和字重就 ok 了吧?殊不知這是造成切出來的網頁與設計
Thumbnail
2023/10/04
切版有許多眉角需要注意,來探討那些經常導致切版結果與設計稿產生落差的原因。 一、文字的高度本體是 line-height:🔍 文字所佔據的高度不是由font-size決定,而是line-hight。一開始練習切版時,都想著設定好字的尺寸和字重就 ok 了吧?殊不知這是造成切出來的網頁與設計
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
這節課的學習目標是了解 CSS 的基本語法結構和使用方法。
Thumbnail
這節課的學習目標是了解 CSS 的基本語法結構和使用方法。
Thumbnail
CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
Thumbnail
CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
Thumbnail
您對前端有興趣,對CSS不陌生。CSS新特性前應瞭解基本內容。CSS屬性制定經歷過程,瀏覽器私有前綴及處理,開發者對新特性漸進增強,優雅降級處理,Web標準定義、作用等。
Thumbnail
您對前端有興趣,對CSS不陌生。CSS新特性前應瞭解基本內容。CSS屬性制定經歷過程,瀏覽器私有前綴及處理,開發者對新特性漸進增強,優雅降級處理,Web標準定義、作用等。
Thumbnail
所有的 CSS 設計模式都是為了維持可讀性、好維護、易擴充這幾個目標,今天就來談談 BEM 設計模式,並搭配 Sass 中的 SCSS 來介紹,並探討在各種情境下該如何使用 BEM。
Thumbnail
所有的 CSS 設計模式都是為了維持可讀性、好維護、易擴充這幾個目標,今天就來談談 BEM 設計模式,並搭配 Sass 中的 SCSS 來介紹,並探討在各種情境下該如何使用 BEM。
Thumbnail
本篇習作內容,除了練習六角預習影音內的常用語法章節外,也額外整理了其它常用於文本的 HTML 元素,希望能透過這樣的整理,在未來設計結構更複雜的網站介面內容時,能扎穩根基。
Thumbnail
本篇習作內容,除了練習六角預習影音內的常用語法章節外,也額外整理了其它常用於文本的 HTML 元素,希望能透過這樣的整理,在未來設計結構更複雜的網站介面內容時,能扎穩根基。
Thumbnail
display 是一種 CSS 屬性,指定「 是否 / 如何 」顯示元素,而每一個 HTML element 都有預設的 display value,然而在預設的情況下,新手如我在剛接觸時常踩入深不見底的盲區, 一起來釐清學會辨識吧!
Thumbnail
display 是一種 CSS 屬性,指定「 是否 / 如何 」顯示元素,而每一個 HTML element 都有預設的 display value,然而在預設的情況下,新手如我在剛接觸時常踩入深不見底的盲區, 一起來釐清學會辨識吧!
Thumbnail
在 Modern Web 的世界中,已經有非常多的套件、語法、框架,可以解決大部分網頁排版問題。 以我近期的觀察來說,在專案開發時,大部分公司會為了讓下一個接手、維護的開發者能更快上手專案架構,而採取原生的 CSS 寫法,而不是仰賴快速又方便的套件。
Thumbnail
在 Modern Web 的世界中,已經有非常多的套件、語法、框架,可以解決大部分網頁排版問題。 以我近期的觀察來說,在專案開發時,大部分公司會為了讓下一個接手、維護的開發者能更快上手專案架構,而採取原生的 CSS 寫法,而不是仰賴快速又方便的套件。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News