[CSS Note] - CSS模組化
Introduction & 前言
記得剛接觸 CSS 的時候覺得就是替東西加上屬性,沒有什麼特別的困難,因為都是一頁式的頁面,只要一支 all.css 就搞定,所以愛怎麼取名字愛怎麼給屬性就寫,慢慢的頁面多了,all.css 慢慢開始千行起跳了 ( 誤…,這時候開始思考 CSS 是否也能有自己的架構。
為什麼要模組化?
一個有規劃有邏輯的專案,不管是一頁式或是大型專案,都需要有自己個規則還有規範,其中好處之一是自己過了一陣子回來看 Code 亦或是其他人接手案子後也能馬上清楚明白整體的架構及方便改寫,另外就是對於網頁的效能上或多或少都能有所幫助,除此之外還能減少你的工程時間。
Summary & 摘要
因為一直對於 CSS 算是一知半解,加上曾經被說過 CSS 命名跟管理很糟糕,最近在自己亂玩 Webpack 時就胡亂爬文學習 Sass 了,用了一陣子剛好碰上六角學院的 Sass 課程在特價(點我選購XD),瞥見課程說明 懂得設計出一手好 CSS 命名 二話不說就買了,剛好課程內提到模組化,深深覺得很有幫助,就索性紀錄下來,偶爾在 CSS 上碰到難處還能回來看看文章。( 所以有寫錯的地方還請大神們手下留情…
在這邊將會主要提到三個架構,你可以都不用,也可以只用其中一個,重點還是看你自己怎麼樣覺得方便。
SMACSS — 偏向整個專案架構的分類及模組化你的 CSS
OOCSS — 使用物件導向方式管理 CSS 的 Style
BEM — 關於 Class的命名方式
不管哪一個類別,其實其中他們都有相似的地方,因為其中某些觀念都是相似的,所以有重疊的地方是正常的,如果你有自己的規範也能試著使用自己的方式,主要還是自己方便且好維護為主,主要記得四大要點:
可預測性( Predictable )
可重複使用性( Reusable )
易維護性( Maintainable )
可擴充性( Scalable )
首先談談 SMACSS
全名為( Scalable and Modular Architecture for CSS ) ,顧名思義是可模組化且具結構分類有命名規則的方式,其中的精神就是容易擴展及模組化。
官方網站的介紹是免費的,傳送門在此 ( 建議詳讀
基本上的結構分為 Base、Layout、Module、State、Theme。
・Base — 網頁基本樣式,還有 CSS Reset。
・Layout — 像是網頁的 hader、footer、sidebar,如果是唯一的區塊可以使用 id 取名;如果是重複出現一樣使用 Class
・Module — 類似 component ,或是常常出現的區塊內容,比如 .list-li
・State — 元件的狀態,例如 .list-li active 最後的 active
・Theme — 樣式,例如 bootstrap 裡的 btn-dark
看完結構後,就能知道怎麼命名,命名規則是在前面加上前綴,透過命名我們可以快速找到 CSS 是什麼類別,並且在大型專案中可以迅速找到在哪個文件中。例如 layout 使用 l- 為開頭,State 的部分則使用 is- 作為前綴,Module 則沒有主要的命名規則,因為 Module 名字太長, SMACSS 建議直接使用 Module 的名稱去命名。
講了這麼多架構,你其實只需要明白兩個步驟。
先把你需要常用到的樣式給一個初始值,這邊用 btn 舉例。
1 | .btn { |
之後其他地方需要用到 button 時,可以再給他第二層的客製樣式。
1 | .btn-danger { |
需要用到客製化的地方在加上後面的 .btn-danger class
這樣一來能有效管理你的 css 命名之外,也不會造成 css 檔案過肥。
但是在 SMACSS 上還是有許多模糊的界線在,其實善用子模組,能讓你的 Class 清楚且少了重複命名的機率產生。
更詳細的介紹可以參考此網站:傳送門
再來談談 OOCSS
( Object Oriented CSS )有兩項基本的原則,結構與樣式分離,容器與內容分離。
OOCSS官方網站:傳送門
其實基本上跟 SMASS 很相近,最好的範例就是 bootstrap 或是 960 Grid。OOCSS 的基本概念在盡量把樣式( CSS )從結構( ul、li、span… )中抽離出來,在把容器( body、container… )跟內容( list-group、page-box… )分開。主要要讓你的 CSS重複使用性拉高,減少網頁效能上過度渲染造成的速度緩慢後果。
結構與樣式分離
假設我們有一個表單,一般我們給予 span css 的方法會這樣下。但是有一個問題是,今天如果我們要在另一個區塊的 span 導入一樣的 css, 勢必要在下一次 css,亦或者今天結構變動,我不要 li 了,css 勢必會吃不到。
1 | .content > div > span{ |
如果我們把這個樣式抽離出來,並且取個名字,盡量不去使用 HTML Tag 這樣就是 結構與樣式分離。
容器與內容分離
這個就比較好懂了,也是盡量避免使用 .left-bar .list-group li span 去命名,除了會造成網頁在渲染時造成效能問題外,如我網頁結構需要變動,那真的是傷透腦筋。
按造上面的取名方法,假如今天 right-bar 需要使用到一樣的 css 我只需要幫他們的 class 加上對應的 css 就好了。
最後來談談 BEM
*這是我覺得最有用也最讓人一目瞭然的方式,你可以不嘗試 SMACSS 可以不嘗試 OOCSS,但你一定要試看看 BEM。**Block( 區塊 )、Element( 元素 )、Modifier( 修飾符 )*。
BEM 理念上強調完全使用 Class Selector 並且以功能導向命名。
BEM官方網站:傳送門
Block — 通常表示可獨立的元件,也可以存在於其他 Block 當中。
Element — 這是存在於 Block 之中的小元件,並且不可單獨分離出來,命名也是功能導向,在自己的前方跟 Block銜接的地方用兩個下底線分開,在自己的名稱斷點使用一個分隔號隔開。
1 | --> Block-name__Element-name // 命名規則 |
Element 可以存在於 Element裡面,但是必須依賴在 Block 之下。
1 | <form class="list-from"> |
Modifier — 這是表述組建的狀態或行為,命名規則上以單底線_或兩橫線- - 。
1 | <form class="list-from"> |
關於 BEM 官方有一套 CSS 分類方式,每一個 Block 都會有自己的資料夾路徑,並且裡面有這個 Block 的專屬 CSS 及 JS。裡面還會有這個 Block 下方 Element 的資料夾,並且開頭為 __ 。
1 | list-from/ |
詳細可以拜讀此篇文章:傳送門
幾個重點整理:
Block 對應一個資料夾,命名相同,每個 Block 資料夾下面都有獨立的 JS 及CSS 檔案。
Element 的資料夾命名採 雙底線 開頭,但是檔案命名一樣要加上 Block 名稱。
Modifier 採單底線,並且 Modifier 下通常只有 CSS 檔案。
Conclusion & 結論
在學 Code 時矇懞懂懂,一開始也不知道有什麼規範規則,這次拜六角學院課程所賜,索性研究了一下關於 CSS 的架構,在之後的練習及專案都會試著導入 SMACSS OOCSS BEM 等等的架構,並且試著找尋最適合自己的方式。
還是那句老話『沒有最好,只有最適合』,希望在成長的這一路上或多或少能幫助到某些在困惑的人,也照著自己最初寫 Blog 的初衷,用 Blog 紀錄自己的成長及缺點,再一段時間之後再回來檢討自己,也希望成長後的我,能幫助到剛開始成長的你。
從最剛開始的六角地下城開始,慢慢的練習 JS 到 Vue.js ,誤打誤撞研究 Webpack 之後現在慢慢學習 Sass,近期內的目標就是能用所學的這些,做出一個類似電商的網站,期許自己的成長,衝吧!
( 會在努力吸取新知更新 CSS 系列的
最後這邊提供一個自己練習照著 SMACSS OOCSS BEM 架構練習的 Source Code,因為是自己第一次練習寫,還能希望有大神能不吝嗇指教。
參考網站
- Segmentfault — CSS设计模式:OOCSS 和 SMACSS
- Summer。桑莫。夏天 — CSS 的模組化方法:OOCSS、SMACSS、BEM、CSS Modules、CSS in JS
- W3C — BEM的定义
- 六角學院 —Sass 實戰全攻略 — 成為前 1% 的 CSS 頂尖好手