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
    7會員
    30內容數
    正在一點一滴學習程式,相信知識量總有一天會匯聚成大海,目前專門研究前端中。
    留言0
    查看全部
    avatar-img
    發表第一個留言支持創作者!
    傑米的沙龍 的其他內容
    除了常見的 Material Icons 和 Font Awesome 提供免費圖示資源,現在又有 「icofont」可以引入 icon 到網頁中了!目前看網路上對它的討論較少,這篇主要會來談談它引入到網頁的方式。
    以往寫網頁經常使用到 Google Fonts 裡的 Material Icons 服務,但大多都是直接引入預設設定,最多就是在官方提供的簡易編輯器做一些 icon 樣式填滿、線框的調整而已,仔細看了官方文件之後,才發現原來還有一些設定可以做調整,使用上更加彈性,因此寫了這篇文章記錄下來。
    JavaScript 的型別可以分為兩類,分別是原始型別與物件型別,這邊主要談的是 ES6 的寫法。值得注意的是,JavaScript 變數本身不帶有型別,值才有。
    npm 是一個套件管理工具,開發中經常需要使用第三方套件,npm 是可以用來管理很多套件的工具,這邊指的套件可能是 Library, 框架, 工具等,例如 Bootstrap, jQuery, Vue.js, babel 都可以統一由它管理。
    除了常見的 Material Icons 和 Font Awesome 提供免費圖示資源,現在又有 「icofont」可以引入 icon 到網頁中了!目前看網路上對它的討論較少,這篇主要會來談談它引入到網頁的方式。
    以往寫網頁經常使用到 Google Fonts 裡的 Material Icons 服務,但大多都是直接引入預設設定,最多就是在官方提供的簡易編輯器做一些 icon 樣式填滿、線框的調整而已,仔細看了官方文件之後,才發現原來還有一些設定可以做調整,使用上更加彈性,因此寫了這篇文章記錄下來。
    JavaScript 的型別可以分為兩類,分別是原始型別與物件型別,這邊主要談的是 ES6 的寫法。值得注意的是,JavaScript 變數本身不帶有型別,值才有。
    npm 是一個套件管理工具,開發中經常需要使用第三方套件,npm 是可以用來管理很多套件的工具,這邊指的套件可能是 Library, 框架, 工具等,例如 Bootstrap, jQuery, Vue.js, babel 都可以統一由它管理。
    你可能也想看
    Google News 追蹤
    Thumbnail
    這節課的學習目標是了解 CSS 的基本語法結構和使用方法。
    Thumbnail
    CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
    Bệt liền khối một khối: Giải mã thuật ngữ và những ưu điểm vượt trội Bệt liền khối một khối là cụm từ thường được sử dụng để mô tả loại bệt vệ sinh c
    Thumbnail
    這篇文章分享了 CSS Battle 第 38 題的解法,並提供了相關的技術總結。文章內容包括了使用 flex 排版處理、背景漸層的方法處理等相關技術。透過這篇文章可以學習到如何解決 CSS 切版的問題。
    在當今日新月異的數位時代,網站已經不僅僅是一個給人們提供資訊的平臺,更是一個互動性、視覺吸引力和功能性兼具的數位體驗。而CSS(Cascading Style Sheets)正是網站設計中的一個重要元素,扮演著關鍵的角色。
    Thumbnail
    本篇文章分享了前端工程師在 CSS Battle #166 的解題方式,藉由使用 flex 來進行排版,並提供了相關的技術總結。歡迎一起來學習或練習基礎切版的朋友們和作者互動。
    Thumbnail
    這是一篇關於CSS Battle系列的文章,介紹瞭如何通過CSS來處理特定圖案的切版與前端工程技術。文章分享了使用grid和radial-gradient()方法來處理特定圖案的解法以及相關技術總結。
    Thumbnail
    在 CSS 的開發過程中,重複使用如顏色、字體大小等值是常見的需求。為了提高程式碼維護性和靈活性,就需要用到 CSS 變量了,CSS 變量可以讓你在樣式表中儲存可重用的值。本文將介紹 CSS 變量的概念、使用方法,以及它對撰寫 CSS 的影響。
    Thumbnail
    本文將介紹 CSS 中的兩個重要概念:偽類與偽元素。通過理解和運用這些概念,你可以更好的控制網頁的樣式和佈局。
    Thumbnail
    您對前端有興趣,對CSS不陌生。CSS新特性前應瞭解基本內容。CSS屬性制定經歷過程,瀏覽器私有前綴及處理,開發者對新特性漸進增強,優雅降級處理,Web標準定義、作用等。
    Thumbnail
    這節課的學習目標是了解 CSS 的基本語法結構和使用方法。
    Thumbnail
    CSS 是控制網頁外觀的語言,應用於網頁設計、UI/UX 設計、電子商務和移動應用開發。主要使用者包括前端開發者、UI/UX 設計師和網頁設計師。CSS 的特性有樣式控制、層疊優先級、響應式設計及分離內容與樣式。
    Bệt liền khối một khối: Giải mã thuật ngữ và những ưu điểm vượt trội Bệt liền khối một khối là cụm từ thường được sử dụng để mô tả loại bệt vệ sinh c
    Thumbnail
    這篇文章分享了 CSS Battle 第 38 題的解法,並提供了相關的技術總結。文章內容包括了使用 flex 排版處理、背景漸層的方法處理等相關技術。透過這篇文章可以學習到如何解決 CSS 切版的問題。
    在當今日新月異的數位時代,網站已經不僅僅是一個給人們提供資訊的平臺,更是一個互動性、視覺吸引力和功能性兼具的數位體驗。而CSS(Cascading Style Sheets)正是網站設計中的一個重要元素,扮演著關鍵的角色。
    Thumbnail
    本篇文章分享了前端工程師在 CSS Battle #166 的解題方式,藉由使用 flex 來進行排版,並提供了相關的技術總結。歡迎一起來學習或練習基礎切版的朋友們和作者互動。
    Thumbnail
    這是一篇關於CSS Battle系列的文章,介紹瞭如何通過CSS來處理特定圖案的切版與前端工程技術。文章分享了使用grid和radial-gradient()方法來處理特定圖案的解法以及相關技術總結。
    Thumbnail
    在 CSS 的開發過程中,重複使用如顏色、字體大小等值是常見的需求。為了提高程式碼維護性和靈活性,就需要用到 CSS 變量了,CSS 變量可以讓你在樣式表中儲存可重用的值。本文將介紹 CSS 變量的概念、使用方法,以及它對撰寫 CSS 的影響。
    Thumbnail
    本文將介紹 CSS 中的兩個重要概念:偽類與偽元素。通過理解和運用這些概念,你可以更好的控制網頁的樣式和佈局。
    Thumbnail
    您對前端有興趣,對CSS不陌生。CSS新特性前應瞭解基本內容。CSS屬性制定經歷過程,瀏覽器私有前綴及處理,開發者對新特性漸進增強,優雅降級處理,Web標準定義、作用等。