Skip to content

CSS 方法論怎麼選?BEM、OOCSS 與 SMACSS 的取捨

CSS 方法論比較:BEM、OOCSS 與 SMACSS 的取捨

三套方法論常被拿來比較,好像得三選一。實際上它們回答的是不同的問題,一起用才是常態。

它們管的不是同一件事

BEMOOCSSSMACSS
回答的問題這個東西該叫什麼?這組樣式該怎麼拆?這段樣式該寫在哪?
產出命名規則拆解原則分類架構
影響的範圍類別名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- 前綴
html
<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 這類框架普及後成了另一個主流選項。它和方法論的關係是這樣:

方法論工具類別
樣式寫在CSSHTML
改版時改CSSHTML
命名成本高,每個元件都要取名幾乎沒有
重複程度CSS 少、HTML 少HTML 重複多,靠壓縮與快取彌補
適合元件語彙明確、設計穩定版型變化多、快速迭代

兩者不互斥。常見做法是 重複出現的元件抽成具名類別,零星微調用工具類別。批次產生工具類別的做法見 工具類別

元件框架出現之後

Vue 的 scoped、React 的 CSS Modules 都會自動幫類別加上不重複的後綴,撞名問題由工具解決,不必再靠命名規則迴避。但有三件事框架沒有替你回答:

  1. 元件內部的類別怎麼命名。 作用域只保證不撞名,不保證讀得懂。
  2. 跨元件的共用樣式放哪裡。 按鈕、表單這些一定會被多個元件共用。
  3. 全域樣式與變數怎麼組織。 重置變數 永遠在作用域之外。

所以方法論並沒有過時,只是需求從「避免撞名」轉成「維持可讀」。CSS Modules 的實際運作見 Sass 與建置工具

怎麼導入到舊專案

不要整包重寫,用這個順序最不痛:

  1. 凍結舊樣式。 舊檔案維持原樣,不再新增內容。
  2. 新元件用新規則。 從最常被複製的那一個開始寫。
  3. 逐區替換。 改到某頁時,順手把那頁用到的元件換成新的。
  4. 最後刪舊檔。 確認沒有頁面引用了,再整批移除。

注意

兩套規則並存的過渡期會比想像中長,一定要在專案文件裡寫清楚哪些目錄是舊的,否則新人會照著舊檔案的寫法繼續加東西。

常見問題

一定要選一套方法論嗎?

重點不是選哪一套,而是全專案用同一套。三套方法論的效果都遠勝過各寫各的,真正造成維護困難的是同一個專案裡並存三種命名習慣。

用 Vue 或 React 還需要方法論嗎?

需要的程度降低了。框架的作用域樣式已經解決撞名問題,但元件內部的類別怎麼命名、共用樣式怎麼拆、全域樣式放哪裡,仍然要有共識。

用了工具類別還需要 BEM 嗎?

看情況。全面採用工具類別的專案,大部分樣式直接寫在 HTML 上,命名規則的需求會少很多;但重複出現的元件仍值得抽成具名類別,這時 BEM 依然適用。

舊專案要怎麼導入?

不要整包重寫。新寫的元件一律照新規則,舊樣式維持不動,兩套暫時並存;等新寫法覆蓋的範圍夠大,再逐區把舊的換掉。

延伸閱讀