SASS-BEM設計模式
什麼是 BEM?
BEM 其實是一種 CSS class 命名的設計模式🤩,把原本的 class 名稱用不同的區塊來做寫法上的區分,讓人更容易閱讀,BEM 分成以下三個:
.block{}
B→ 區塊 (Block).block__element{}
E→ 元素 (Element).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 都是客製化的情況下,這樣在閱讀時是不是有一點混淆?
到底 menu
是 news
的還是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。
大概是兩種:
- 工具類 class: 清除浮動
.clearfix{clear:both}
、推移.mb-12{margin-bottom:12px}
、文字顏色.color-secondary{color:black}
...等。 - 元件 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 名稱,就馬上了解你怎麼寫的,什麼是容器,有沒有重複使用的套件,哪個是樣式。
這樣如果要改設計,就能了解怎麼修改更快速且準確~