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 設計模式的分享就到這裡,若有錯誤歡迎指正,感謝看完這篇的大家。

    7會員
    30內容數
    正在一點一滴學習程式,相信知識量總有一天會匯聚成大海,目前專門研究前端中。
    留言0
    查看全部
    發表第一個留言支持創作者!
    傑米的沙龍 的其他內容
    除了常見的 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
    這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
    Thumbnail
    美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
    Thumbnail
    Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
    Thumbnail
    繼先前問世的「Citrus Milk」後,Salehe Bembury 近日又在 Instagram 宣布,Crocs Pollex Slides 拖鞋即將推出全藍新配色「Tashmoo」。 這款在鞋身、鞋底皆帶有指紋設計的拖鞋,已經成為該聯乘系列不可或缺的經典特徵,鞋床上的節點可以增加穿著時的舒
    Thumbnail
    超超超好看呀,這種掰彎情敵的故事,我好喜歡呀!類似 #求婚大作戰 ,回到過去,改變自己,卻也讓別人注意到原本不起眼的他。這可是暖暖自一年生後再度接拍BL的作品,看預告,就覺得超有質感呀!然
    Thumbnail
    MongoDB非常擅長查詢大量的數據並經常更新這些資訊, 在多數的情況之下, 我們只要查詢資訊最新的狀態, 那假設我們需要查詢資料的上一個狀態呢? 如果我們需要一些文檔版本控管功能時怎麼辦呢? 這就是我們可以使用版本控管設計模式的地方了。 這個模式之下會保存文檔的歷史版本, 我們就不用導入另外一個版
    Thumbnail
    fast endpoints 是一個支援 .NET 6 以上(Nuget 版本清單) 的 API 輕量框架,雖以簡單與高性能為主打,但也提供了很多常用的功能實現,如 Swagger 整合、Jwt 認證、Api 版本控制、APi 速率限制、Api 回應快取…很適合以此為基礎打造 Api 服務。
    Thumbnail
    小心設計模式別亂用 📷 介紹 設計模式就是過去的人,根據常見的軟體設計的問題,提出的解決方案。 設計模式總共有23種,根據情境分成三大類型,建立型、結構型、行為型。 建立型模式(Creational Patterns) 簡單工廠(Simple Factory) 工廠方法(Factory) 抽象工廠
    Thumbnail
    K大怎麼建立自己的飛輪,並且持續利用綜效,創造出巨大效益呢?
    Thumbnail
    許多人想要開始經營自己的斜槓事業,雖然腦中大致有個初步的方向,或是大約了解自己的興趣和方向,但仍不確定如何開始設計自己的個人品牌商業模式。 而有了商業模式的設計之後,在撰寫部落格文章也將各有系統和方向,也更容易駕馭相對應的行動呼籲喔! 這篇文章你可以學習到如何設計你的個人品牌商業模式-->
    Thumbnail
    我是部落客,也要設計產品服務區嗎? 是的!Winnie建議你在自己的部落格網站上放上自己設計的產品服務區! 有一些人可能會認為自己只是純粹寫部落格分享自己的想法,並尚未準備提供產品或服務,或是認為自己的人氣還不夠,即使推出產品或服務也不會有人購買,所以就不先設計「產品服務區」了,但我還是非常推薦..
    Thumbnail
    但是德國的集中和組織卻沒有鬥過英國的自由和法國的民主,因為儘管德國組織得更好一些,但是卻抵擋不住英國的海運控制的全世界資源和美國加入以後更大的人力和生產能力。但是德國的組織也確實有它的能力。大致上講,德國人如果是在對方優勢不超過四倍的情況下,德國人至少能打平手。雙方力量相等的情況下,德國人每次都打贏
    Thumbnail
    這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
    Thumbnail
    美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
    Thumbnail
    Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
    Thumbnail
    繼先前問世的「Citrus Milk」後,Salehe Bembury 近日又在 Instagram 宣布,Crocs Pollex Slides 拖鞋即將推出全藍新配色「Tashmoo」。 這款在鞋身、鞋底皆帶有指紋設計的拖鞋,已經成為該聯乘系列不可或缺的經典特徵,鞋床上的節點可以增加穿著時的舒
    Thumbnail
    超超超好看呀,這種掰彎情敵的故事,我好喜歡呀!類似 #求婚大作戰 ,回到過去,改變自己,卻也讓別人注意到原本不起眼的他。這可是暖暖自一年生後再度接拍BL的作品,看預告,就覺得超有質感呀!然
    Thumbnail
    MongoDB非常擅長查詢大量的數據並經常更新這些資訊, 在多數的情況之下, 我們只要查詢資訊最新的狀態, 那假設我們需要查詢資料的上一個狀態呢? 如果我們需要一些文檔版本控管功能時怎麼辦呢? 這就是我們可以使用版本控管設計模式的地方了。 這個模式之下會保存文檔的歷史版本, 我們就不用導入另外一個版
    Thumbnail
    fast endpoints 是一個支援 .NET 6 以上(Nuget 版本清單) 的 API 輕量框架,雖以簡單與高性能為主打,但也提供了很多常用的功能實現,如 Swagger 整合、Jwt 認證、Api 版本控制、APi 速率限制、Api 回應快取…很適合以此為基礎打造 Api 服務。
    Thumbnail
    小心設計模式別亂用 📷 介紹 設計模式就是過去的人,根據常見的軟體設計的問題,提出的解決方案。 設計模式總共有23種,根據情境分成三大類型,建立型、結構型、行為型。 建立型模式(Creational Patterns) 簡單工廠(Simple Factory) 工廠方法(Factory) 抽象工廠
    Thumbnail
    K大怎麼建立自己的飛輪,並且持續利用綜效,創造出巨大效益呢?
    Thumbnail
    許多人想要開始經營自己的斜槓事業,雖然腦中大致有個初步的方向,或是大約了解自己的興趣和方向,但仍不確定如何開始設計自己的個人品牌商業模式。 而有了商業模式的設計之後,在撰寫部落格文章也將各有系統和方向,也更容易駕馭相對應的行動呼籲喔! 這篇文章你可以學習到如何設計你的個人品牌商業模式-->
    Thumbnail
    我是部落客,也要設計產品服務區嗎? 是的!Winnie建議你在自己的部落格網站上放上自己設計的產品服務區! 有一些人可能會認為自己只是純粹寫部落格分享自己的想法,並尚未準備提供產品或服務,或是認為自己的人氣還不夠,即使推出產品或服務也不會有人購買,所以就不先設計「產品服務區」了,但我還是非常推薦..
    Thumbnail
    但是德國的集中和組織卻沒有鬥過英國的自由和法國的民主,因為儘管德國組織得更好一些,但是卻抵擋不住英國的海運控制的全世界資源和美國加入以後更大的人力和生產能力。但是德國的組織也確實有它的能力。大致上講,德國人如果是在對方優勢不超過四倍的情況下,德國人至少能打平手。雙方力量相等的情況下,德國人每次都打贏