CSS 命名規範
BEM
命名規範要解決的問題
// 無意義的命名
.block1 {
text-align: center;
background: red;
}
// 如果每個頁面都有 block2,但卻有不同的樣式?
.block2 {
text-align: center;
background: blue;
}
// 充滿惡意的寫法
.text-center {
text-align: left;
}
BEM 組成
- 區塊 (Block)
- 元素 (Element)
- 修飾符 (modifier)
BEM 規範簡述
BEM 規範簡述
區塊(Block)
由多元素組合而成的元件
BEM 規範簡述
BEM 規範簡述
元件 (Element)
組成 Block 的獨立元素
原則上是只有一個功能,不可拆分的元素
Element 以兩個 _ 符號作為連接
BEM 規範簡述
元件 (Element)
.stick-man__head {}
.stick-man__arms {}
.stick-man__feet {}
比方說,這個火柴人有:
- 一個頭部( head )
- 兩隻手臂( arms )
- 雙腳( feet )
Element 以兩個 _ 符號作為連接
BEM 規範簡述
修飾符 (Modifiers)
如同字面的意思
修飾符可直接
依附在 Block 或是 Element 上
Modifiers 以 -- 符號作為連接
BEM 規範簡述
修飾符 (Modifiers)
.stick-man--blue { }
.stick-man--red { }
假設長得一模一樣的火柴人
紅色 (red) 與 藍色 (blue)
Modifiers 以 -- 符號作為連接
BEM 規範簡述
修飾符 (Modifiers)
.stick-man--blue { }
.stick-man--red { }
假設長得一模一樣的火柴人
紅色 (red) 與 藍色 (blue)
Modifiers 以 -- 符號作為連接
BEM 規範簡述
修飾符 (Modifiers)
.stick-man__head--small { }
.stick-man__head--big { }
假設長得一模一樣的火柴人
頭小 (small) 與 頭大 (big)
Modifiers 以 -- 符號作為連接
以上就是 BEM
基本用法了
BEM 與 命名空間
可以直接在 Block 加上命名空間
-
Layouts 佈局
-
Objects 物件
-
Components 組件
-
Utility 實用工具
-
States 狀態
-
JavaScript hooks
BEM 與 命名空間
Layouts 佈局
例如 l-header l-wrap l-footer
Layout 用來定義這些「大架構」
.l-wrap {
width: 100%;
padding-left: 1em;
padding-right: 1em;
margin-right: auto;
margin-left: auto;
}
l-(Layout)
BEM 與 命名空間
Objects 物件
例如 o-button
依據個人習慣可以選擇下列的方式進行命名
1. o-(Objects)物件
2. e-(Element)元素
3. u-(Unit)零件
網頁中的最小構建塊
裡面不能包含其他物件或組件
BEM 與 命名空間
Components 組件
依據個人習慣可以選擇下列的方式進行命名
1. c- (Component)
2. m- (Module)
組件 (Component) 裡面
可以包含很多 物件 (object)
BEM 與 命名空間
Utility 工具
Utility 工具
獨立 且 可以直接
附加在任何 Component 與 Object 的樣式
依據個人習慣可以選擇下列的方式進行命名
1. u-(Utility)
2. h-(Helpers)
3. f-(Fuctions)
例如: u-mt 、 u-mt--large
BEM 與 命名空間
States 狀態
狀態類 (States) 表示物件/組件的當前狀態,通常會搭配 JavaScript 做使用
依據個人習慣可以選擇下列的方式進行命名
1. is-
2. has-
例如: is-active、has-loaded
BEM 與 命名空間
JavaScript hooks
js- 表示物件或組件是否需要用到 JavaScript
碰見問題:
在用 jQuery 可以常常看到這樣的寫法:
$('.nav–main a')
一旦 CSS 發生重構,JavaScript 代碼也將變得難以維護,分不清哪些代碼會受到影響
BEM 與 命名空間
JavaScript hooks
js- 表示物件或組件是否需要用到 JavaScript
<li class="nav__item js-nav__item"></li>
使用 js- 來表示
這樣看到 js-nav__item 馬上就可以知道 nav__item 需要 JavaScript 才能正常工作
BEM 與 SASS
利用 Sass 的 & 父連接詞與巢狀你可以很輕鬆的寫出 BEM 命名結構
<nav class="c-menu c-menu--lg">
<ul class="c-menu__list">
<li class="c-menu__item">
<a class="c-menu__link"></a>
</li>
<li class="c-menu__item">
<a class="c-menu__link"></a>
</li>
</ul>
</nav>
BEM 與 SASS
.c- {
/* style */
&menu {
...
&__list {
/* style */
}
&__item {
/* style */
}
&__link {
/* style */
}
&--lg {
/* style */
}
&--lg &__item {
/* style */
}
&--lg &__link {
/* style */
}
}
}
BEM 會遇到的問題
如何處理 Element 的子元素
當你需要選擇一個嵌套超過兩層的元素
也就是 element 裡面還有 element
<nav class="c-menu">
<ul class="c-menu__list">
<li class="c-menu__list__item">
<a class="c-menu__list__item__link"></a>
</li>
<li class="c-menu__list__item">
<a class="c-menu__list__item__link"></a>
</li>
</ul>
</nav>
有人可能會這樣寫:
這種方式會很快就會脫離控制
並且一個組件嵌套的越深,可讀性就會變得越差
如何處理 Element 的子元素
<nav class="c-menu">
<ul class="c-menu__list">
<li class="c-menu__item">
<a class="c-menu__link"></a>
</li>
<li class="c-menu__item">
<a class="c-menu__link"></a>
</li>
</ul>
</nav>
回歸基本 B__E--M 的原則,的寫法
- 命名只是用來幫助你識別子元素和頂層組件塊的關係
- 沒必要在類名中呈現 HTML 的結構
另外這也表示所有的子元素都僅僅會被 .c-menu 影響,link 不會綁死在 item 下,也可以新增在 list 外
組件的樣式微調
<nav class="c-menu">
<button class="o-button o-button--primary">Click me!</button>
</nav>
當 o-button 這個 object 的類別
在 c-menu 要額外加點 圓角 的樣式時,要如何處理 ?
只要加一個 c-menu__c-button 的類別名稱在 o-button 之後
按照 CSS 的載入順序,進行附加的樣式就可以了
<nav class="c-menu">
<button class="o-button c-menu__o-button">Click me!</button>
</nav>
這是官方提供的 Mixed 的方法
組件會不會最終有
無數個 class 名稱
但這並非個問題,因為這意味著代碼更具有可讀性,你更能清楚的知道它是用來實現什麼的
<button class="c-button c-button--primary is-active">
Click me!
</button>
如下列的例子:
第一眼看到的時候覺得語法不是最簡潔的,但是非常清晰
參考資料
CSS 設計模式 BEM
By ZHI-WEI HUANG
CSS 設計模式 BEM
- 67