CSS 方法論怎麼選?BEM、OOCSS 與 SMACSS 的取捨
三套方法論常被拿來比較,好像得三選一。實際上它們回答的是不同的問題,一起用才是常態。
它們管的不是同一件事
| BEM | OOCSS | SMACSS | |
|---|---|---|---|
| 回答的問題 | 這個東西該叫什麼? | 這組樣式該怎麼拆? | 這段樣式該寫在哪? |
| 產出 | 命名規則 | 拆解原則 | 分類架構 |
| 影響的範圍 | 類別名 | CSS 與 HTML 的對應 | 檔案結構與載入順序 |
| 主要代價 | 名字長、不好搜尋 | HTML 類別變多 | 前期要先建立分類共識 |
| 導入成本 | 低,看得懂就能寫 | 中,需要判斷抽象時機 | 高,要先討論邊界 |
一句話總結:SMACSS 分檔案、OOCSS 拆樣式、BEM 取名字。
最常見的組合
實務上最順的一套是三個都用,各取所長:
styles/
├─ base/ ← SMACSS 的 Base
├─ layout/ ← SMACSS 的 Layout,l- 前綴
├─ modules/ ← SMACSS 的 Module,內部用 BEM 命名
│ ├─ _button.css .btn / .btn--primary(OOCSS 拆成基底與變化)
│ └─ _card.css .card / .card__title
└─ state/ ← SMACSS 的 State,is- 前綴<button class="btn btn--primary is-loading">送出</button>這一行同時用上三套:btn 是 OOCSS 的結構基底、btn--primary 是 BEM 的修飾子、is-loading 是 SMACSS 的狀態。
依專案規模選
| 情境 | 建議 |
|---|---|
| 一頁式、兩週內結束 | 只要命名一致就好,不必套任何一套。 |
| 一個人維護的中型網站 | BEM 命名 + 依元件拆檔,不必做滿五類分類。 |
| 多人協作、長期維護 | 三套併用,並把規則寫進專案文件。 |
| 需要換膚或多品牌 | 一定要有 SMACSS 的 Theme 分類,或改用 CSS 變數。 |
小提醒
選哪一套遠不如 全專案用同一套 重要。真正讓樣式難以維護的,是同一個專案裡並存三種命名習慣。
工具類別出現之後
把每個屬性做成一個類別(.mt-4、.flex、.text-center)的做法,在 Tailwind 這類框架普及後成了另一個主流選項。它和方法論的關係是這樣:
| 方法論 | 工具類別 | |
|---|---|---|
| 樣式寫在 | CSS | HTML |
| 改版時改 | CSS | HTML |
| 命名成本 | 高,每個元件都要取名 | 幾乎沒有 |
| 重複程度 | CSS 少、HTML 少 | HTML 重複多,靠壓縮與快取彌補 |
| 適合 | 元件語彙明確、設計穩定 | 版型變化多、快速迭代 |
兩者不互斥。常見做法是 重複出現的元件抽成具名類別,零星微調用工具類別。批次產生工具類別的做法見 工具類別。
元件框架出現之後
Vue 的 scoped、React 的 CSS Modules 都會自動幫類別加上不重複的後綴,撞名問題由工具解決,不必再靠命名規則迴避。但有三件事框架沒有替你回答:
所以方法論並沒有過時,只是需求從「避免撞名」轉成「維持可讀」。CSS Modules 的實際運作見 Sass 與建置工具。
怎麼導入到舊專案
不要整包重寫,用這個順序最不痛:
- 凍結舊樣式。 舊檔案維持原樣,不再新增內容。
- 新元件用新規則。 從最常被複製的那一個開始寫。
- 逐區替換。 改到某頁時,順手把那頁用到的元件換成新的。
- 最後刪舊檔。 確認沒有頁面引用了,再整批移除。
注意
兩套規則並存的過渡期會比想像中長,一定要在專案文件裡寫清楚哪些目錄是舊的,否則新人會照著舊檔案的寫法繼續加東西。
常見問題
一定要選一套方法論嗎?
重點不是選哪一套,而是全專案用同一套。三套方法論的效果都遠勝過各寫各的,真正造成維護困難的是同一個專案裡並存三種命名習慣。
用 Vue 或 React 還需要方法論嗎?
需要的程度降低了。框架的作用域樣式已經解決撞名問題,但元件內部的類別怎麼命名、共用樣式怎麼拆、全域樣式放哪裡,仍然要有共識。
用了工具類別還需要 BEM 嗎?
看情況。全面採用工具類別的專案,大部分樣式直接寫在 HTML 上,命名規則的需求會少很多;但重複出現的元件仍值得抽成具名類別,這時 BEM 依然適用。
舊專案要怎麼導入?
不要整包重寫。新寫的元件一律照新規則,舊樣式維持不動,兩套暫時並存;等新寫法覆蓋的範圍夠大,再逐區把舊的換掉。