---
# System prepended metadata

title: BEM 學習
tags: [SCSS/BEM, OKR, 自主學習]

---

<style>
.title{
 font-size:20px;
 font-weight:bold;
 color:#283593;
}
</style>

# BEM 學習
###### tags: `OKR` `自主學習` `SCSS/BEM`
###### 2020/07/11(Update)

## 7/11學習內容

學習來源：
[BEM官方文件](http://getbem.com/introduction/)
[youtube資源學習](https://www.youtube.com/watch?v=er1JEDuPbZQ&t=308s)

---

<div class="title">什麼是BEM？</div>

1. 以Block結構來命名Html Class Name。
2. 全名叫Block／Element／Modifier。
3. Block：一個區塊包覆相同的內容結構，例如下方卡片範例，卡片最外面的一層就叫Block。
4. Element：卡片裡面的各項內容抽出來就叫element，例如圖片img／標題title／描述desc／按鈕button。
5. Modifier：代表修飾符號名稱，比較簡單的說法是這個Element狀態事件發生或是形體上的改變、不同的類型，例如我們專案上常會寫到按鈕被active或是卡片有分light/dark類型，如下範例。

<center class="half">
    <img src="https://i.imgur.com/6XuX1B0.png" />
    <p>BEM命名範例</p>
</center>


```sass
<div class="card card--light"></div>
<div class="card card--dark"></div>
```
<div style="text-align:center">形體上的改變、不同的類型</div>
<br>


<div class="title">用BEM的好處是什麼</div>

1. 雖然感覺Class命名變長，但整體結構能讓沒寫這專案的人都能快速理解。
2. 命名很長的問題，透過搭配撰寫SCSS就可解決。
3. 很多命名會重覆的區塊就可以模組化共用使用。
4. 變的更好維護。

<div class="title">BEM基本寫法</div>

如果是Element：blockname__elementname ( 二個下底線 _ _ )
```htmlmixed
<div class="card__title"></div>
```

如果是Modifier：blockname__elementname--ModifierStatus ( 二個連字符 - - )
過往都是直接寫active／hidden／success 等寫法，BEM寫法換成以下方式
```htmlmixed
<div class="card__button card__button--active"></div>
<div class="card__button card__button--is-active"></div>
<div class="card__button card__button--is-hidden"></div>
```

<div class="title">使用SCSS撰寫BEM樣式</div>

當Html架構寫好後，開始撰寫BEM樣式，結合SCSS寫法
```sass
/* SCSS結構 */

.card{
 &__title{.....}
 &__button{
     //......
     &--active{.......}
 }
}
```

```sass
/* CSS編譯結果 */

.card__title{....}
.card__button{.....}
.card__button--active{.....}
```

Classname也可以加上 ' - '，使用前缀
```htmlmixed
<form class="site-search  site-search--full">
    <input type="text" class="site-search__field">
    <input type="Submit" value ="Search" class="site-search__button">
</form>
```
```sass
/* SCSS結構 */
.site-search{}
.site-search__field{}
.site-search__button{}
.site-search--full{}
```


<div class="title">BEM最好的寫法</div>

在撰寫時，除了更換命名的方式，但撰寫SCSS結構時也需要一併思考，整個結構先以一個Block命名開始，其它必須統一一致，例如：
```htmlmixed
<button class="button">基本按鈕</button>
<button class="button button--state-success">成功按鈕</button>
<button class="button button--state-danger">警示按鈕</button>
```
我們應該怎麼寫SCSS？
```sass
/* 1.首先先寫好預設按鈕的結構 */
.button{
    border-radius: 3px;
    padding: 7px 12px;
    border: 1px solid #D5D5D5;
    font-size:16px;
    text-align:center;
    
    /* 2.在把Modifier所需狀態使用的SCSS寫出來 */
    &--state-success{
        color: #FFF;
        background: #569E3D linear-gradient(#79D858, #569E3D) repeat-x;
        border-color: #4A993E;
    }
    &--state-danger{
        color: #900;
    }
}
```


<div class="title">撰寫時遇到的問題紀錄</div>

#### 問題一
實際撰寫時，當使用Modifiter時--active，雖然搭配SCSS天衣無縫，不需要寫太長的名稱，但若是使用在JS上時，你必須要將完整的Classname寫上去，雖然一樣名稱太長，但一樣若能讓每個人容易理解之優點來說還是大過於此缺點，也或許是自己可能還沒尋找到最佳方法。

```javascript
$('.card__button').addClass('.card__button--active');
```

#### 問題二
實際撰寫時一定要整個結構一致，否則會吃不到子層的樣式，遇到問題是希望在同層加上同一結構但不同類型的Class狀態。

例如這張卡片需要dark(暗色系)或是light(亮色系)。下方範例會發什麼事情，.card.light的樣式會吃不到底下的.card__item樣式，意思是CSS沒辦法吃到(.card.light .card__item)，猜測應該是撰寫BEM規則時，SCSS在編譯時可能沒法整併。

```sass
/* 1.light or dark 非BEM寫法 */
<div class="card light">
    <div class="card__item"></div>
    <div class="card__item"></div>
    <div class="card__item"></div>
</div>
<div class="card dark">
    <div class="card__item"></div>
    <div class="card__item"></div>
    <div class="card__item"></div>
</div>
```
```sass
/* 2.當撰寫時，SCSS to css 吃不到__item */
.card{
    &.light{
        &__item{
        ........
        }
    }
    &.dark{
         &__item{
        ........
        }
    }
   
}
```

改寫方法：
```sass
/* 1.加上modifier類型 */
<div class="card card--light">
    <div class="card__item"></div>
    <div class="card__item"></div>
    <div class="card__item"></div>
</div>
<div class="card card--dark">
    <div class="card__item"></div>
    <div class="card__item"></div>
    <div class="card__item"></div>
</div>
```
```sass
/* 2.先寫好card基本結構，並在給予light/dark增加顏色樣式等內容 */
.card{
    //3.這裡寫card基本結構
    .....
    //4.再來針對light/dark寫樣式
    &--light{
        color:#ffffff;
    }
    &--dark{
        color:#000000;
    }
    .__item{
     .....    
    }
}

```
這樣每個class在同一個card Block底下結構均都不受影響，不需要為了某個結構在重覆改寫。

#### 問題三
在查看BEM官方文件[CSS層疊繼承所帶來的問題](https://www.phase2technology.com/blog/used-and-abused-css)，發現了原來自己撰寫時也可能會犯下的不好習慣，有些地方過度濫用CSS層疊繼承，覆蓋原有編寫的樣式問題。下方的圖片反而造成樣式不斷被重覆改寫，程式碼太多/浪費等問題。

<center class="half">
    <img src="https://i.imgur.com/3IVwTCs.png" />
    <p>CSS層疊繼承</p>
</center>

改寫方法：
如同模組化的概念，樣式應該要更加彈性，應該是要可獨立／可重用／不受任何父層影響／更好維護。