SASS-BEM設計模式

Jordan Tseng
JordanTTCDesign
Published in
8 min readNov 4, 2020

什麼是 BEM?

BEM 其實是一種 CSS class 命名的設計模式🤩,把原本的 class 名稱用不同的區塊來做寫法上的區分,讓人更容易閱讀,BEM 分成以下三個:

  1. .block{} B→ 區塊 (Block)
  2. .block__element{} E→ 元素 (Element)
  3. .block--modifier{} M→ 修飾符 (Modifier)

class 這樣寫有什麼好處呢?

就是只要看 class 名稱就能夠快速的告訴開發者,這些樣式彼此關係是什麼?😍😍我們先以下面一般 class 寫法的例子來看看:

<section class="news">
<ul class="menu">
<li class="item active"><a href="#"></a></li>
<li class="item"><a href="#"></a></li>
</ul>
</section>
<section class="hotels">
<ul class="menu">
<li class="item active"><a href="#"></a></li>
<li class="item"><a href="#"></a></li>
</ul>
</section>

在每一 css 都是客製化的情況下,這樣在閱讀時是不是有一點混淆?

到底 menunews 的還是hotels 的?

但如果像下面使用 BEM 的寫法,就會比較看得出誰是誰的親戚了:

<section class="news">
<ul class="news__menu">
<li class="news__menu__item news__menu__item--active">
<a href="#"></a></li>
<li class="news__menu__item"><a href="#"></a></li>
</ul>
</section>
<section class="hotels">
<ul class="hotels__menu">
<li class="hotels__menu__item hotels__menu__item--active">
<a href="#"></a></li>
<li class="hotels__menu__item"><a href="#"></a></li>
</ul>
</section>

當然 menu 可以另外抽出來做成元件,裡面的 item 就會寫成 menu__item

知道了 BEM 的好處後,我們正式來分別 BEM 了解的每一個部分吧~~

Block 區塊

區塊,可以指在網頁中的容器,有大有小像是:表頭、選單、banner、彈跳視窗等,一般我們會用語意化的方式命名,像是 .menu .banner .pop。

上面提到有大有小的意思是,區塊裡面的東西不一定要寫成元素,如果他可以獨立在開發中重複使用,也可以視為區塊。

以下我們用一個假的畫面來判斷哪些可能是區塊:

區塊:紫色框。

元素 (Element)

元素 element 可以把它想成是區塊的子元素,與區塊有語義關連性的元件,視為不能跟區塊分開的一部分。以下圖為例:人力資源列表中有五個元素,而在人才列表中也有四個人才元素。

元素的 class 名稱寫法是以兩個下底線與區塊做串連:

.區塊__元素{}
//萬一還有下層還能繼續寫成:
.區塊__元素__元素{}
區塊:紫色框。元素:橘色框。

所以上面的案例,在 css 就會寫成

.nav__item{}
.candidateNav__item{}

修飾符(Modifier)

修飾符 Modifier 在有時候會跟 Element 搞混,到底這時候要視為哪個?

把握一個重點:當區塊或元素因為外觀、狀態或行為改變時,那這個型態轉變就是修飾符。

而修飾符的 class 寫法是用兩個中線做串連🤯,像下面的

.區塊__元素--修飾符{}
.元素--修飾符{}
區塊:紫色框。元素:橘色框。修飾符:綠色框。

所以上面的案例,在 css 就會寫成:

.nav__item—-active{}//瀏覽紀錄
.sideList__item—-active{}//側邊欄
.btn—-primary{}//藍色按鈕

我們把三個一起綜合來看看,運用完整 bem 寫法的結構吧:)

<ul class="nav"> 
<li class="nav__item">
<h5 class="nav__item__title">我是卡片中的標題</h5>
<p class="nav__item__txt">我是卡片中的小字</p>
<a class="nav__item__btn btn">小按鈕</a>
</li>
<li class="nav__item nav__item--active">
<h5 class="nav__item__title color--active">我是卡片中的標題</h5>
<p class="nav__item__txt color--active">我是卡片中的小字</p>
<a class="nav__item__btn btn btn--primary">小按鈕</a>
</li>
</div>

上面把狀態轉變都給拆出來成一個獨立 class,就是不會把原本預設的 class 寫髒的方式唷~

什麼時候不用完全遵守 BEM ?

不是說每個地方都要使用 bem 的唷~要是情況而定,要判斷該元件是否不用跟區塊有關連,是否可以獨立成為的 class。

大概是兩種:

  1. 工具類 class: 清除浮動 .clearfix{clear:both}、推移 .mb-12{margin-bottom:12px} 、文字顏色 .color-secondary{color:black}...等。
  2. 元件 module:可以重複出現在網頁不同地方的元件,像是卡片、列表這種就是可以獨立寫成class 模組。
//小卡模組
.card{
.card__title{}
.card__txt{}
}
//列表模組
.list{
.list__item{
.list__item__txtbox{}
}
}

當然不是在網頁中每個小卡都長一模一樣,也是需要客製化的,可以選擇兩個方式:

用工具類 class 去修改:

<div class="card w-50">    
<h5 class="card__title color--secondary">我是卡片中的標題</h5>
<p class="card__txt ">我是卡片中的小字</p>
<a class="card__btn btn btn--primary">小按鈕</a>
</div>

在 scss 中用父層去包裹,覆蓋前面的樣式:

.section-news{
.list{ width:60%; }
}

用 SCSS 寫 BEM 更好

一般 BEM 寫法會讓人覺得不好的地方是重複地方寫太多次了

.card{}
.card__title{}
.card__txt{}
.card__btn{}

這個不止是單純寫的時候麻煩,改的時候也很麻煩,要改很多次。

所以使用 SCSS 預處理器方式來撰寫,會更方便喔!!

.card{
&__title{
&--active{}
}
&__txt{}
&__btn{}
}

最後要注意一件事情,BEM 的寫法如果一根筋的使用,遇到下面的情況,就會變成很多階層、非常長的 class名稱,其實是很惱人的。

<nav class="menu">
<ul class="menu__list">
<li class="menu__list__item">
<a class="menu__list__item__link"></a>
</li>
<li class="menu__list__item">
<a class="menu__list__item__link"></a>
</li>
</ul>
</nav>

我們可以視情況改寫成區塊就只保留 menu ,元素只保留當前的 li 或 a 等元素就好,更簡潔唷~

可以嘗試看看!!

<nav class="menu">
<ul class="menu__list">
<li class="menu__item">
<a class="menu__link"></a>
</li>
<li class="menu__item">
<a class="menu__link"></a>
</li>
</ul>
</nav>

總結

BEM 用途就是讓你或是一起工作的同事在讀文件時,即便是經過長年累月,只要一看 HTML 中的class 名稱,就馬上了解你怎麼寫的,什麼是容器,有沒有重複使用的套件,哪個是樣式。

這樣如果要改設計,就能了解怎麼修改更快速且準確~

更多資源請參考:

https://ithelp.ithome.com.tw/articles/10160545

https://chupainotebook.blogspot.com/2019/05/bemcss.html

--

--