淺談 CSS 設計模式-SMACSS 篇

前言

CSS 設計模式是一個觀念、規範以及心法,最主要就是要替我們提高開發與維護的效率。

SMACSS

SMACSS 其實是一個縮寫,我們可以透過 官方網站 了解到其實全名是「Scalable and Modular Architecture for CSS」,中文意思是可以擴展且模組化的 CSS 架構。

而 SMACSS 其中主要的核心架構是以下

  • Base
  • Layout
  • Module
  • State
  • Theme

Base (基礎)

Base 是屬於所有網站的基礎架構,概念與 CSS Reset 概念雷同,因此 CSS Reset 就是屬於 SMACSS 中的 Base 的一種。

因此假使來講今天有一段 CSS 像以下這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.header a {
color: red;
display: inline-block;
height: 240px;
}

.footer a {
color: red;
display: inline-block;
height: 290px;
}

.main a {
color: red;
display: inline-block;
height: 210px;
}

在上述中我們可以看到 a 這個超連結標籤都有幾個個共通的 CSS 屬性也就是 color: red; 以及 display: inline-block;,因此我們可以基於 SMACSS Base 核心觀念將這兩個 CSS 設置成網站預設樣式

因此我們可以改寫成這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a {
color: red;
display: inline-block;
}

.header a {
height: 240px;
}

.footer a {
height: 290px;
}

.main a {
height: 210px;
}

我們可以看到 a 連結的基礎樣式就可以變成通用樣式且可以減少 CSS 重複撰寫,通過這種方式我們可以滿足網頁上八成的樣式,那至於剩下的兩成呢?此時就會使用覆蓋的概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a {
color: red;
display: inline-block;
}

.header a {
height: 240px;
}

.footer a {
height: 290px;
}

.main a {
color: white;
height: 210px;
}

所以 Base 的核心觀念在於「在一開始就賦予整個網頁的預設初始樣式,進而減少重複的預設樣式」,因此若某一天需要修改預設樣式時,就只需要調整 Base 即可。

在 SCSS 中通常我們會將 Base 的相關設定獨立出來成一個檔案叫做 _base.scss,並在 CSS Reset 之後,因此在引入時的結構就會像這樣

1
2
3
@import '_variable.scss';
@import '_reset.scss';
@import '_base.scss';

當然你也可以將 Base 寫在 reset,可是以我自己的習慣來講,我會將 reset 獨立,主要是增加 CSS 彈性,舉例來說,若我將 Base 寫在 reset,所以這個 reset 支援 A 網站,但當轉移網站時,他就不支援 B 網站,因此通常會比較傾向 CSS Reset 獨立成一隻會較好。

前面講了很多 Base 基本觀念,但沒有實際應用其實很難了解一個所以然,因此這邊可以參考 Yahoo! 開發的 Pure.css Base

其實 Pure.css 的 Base 非常的小,而他使用的 CSS Reset 是 normalize 來調整成自己的 Base。

Layout (佈局)

Layout 主要用於共用的頁面,舉例來講 header 以及 footer,因此通常我們會將 Layout 獨立出一隻來寫 header、footer 以及 nav 等。

1
2
3
4
@import '_variable.scss';
@import '_reset.scss';
@import '_base.scss';
@import '_layout.scss';

使用 Layout 的觀念可以幫助我們若要調整 header 或 footer 時,就可以非常直覺的找 _layout.scss 調整。

當然 Layout 不只有用於 header 或 footer,假使若有三四個頁面底下都是使用相同的樣式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.indexCard {
border: 1px solid #ffffff;
width: 200px;
font-size: 12px;
}

.carCard {
border: 1px solid #ffffff;
width: 200px;
font-size: 12px;
}

.orderCard {
border: 1px solid #ffffff;
width: 200px;
font-size: 12px;
}

因此這些樣式其實都非常雷同,在維護上就會非常麻煩,當然這邊也有人可能會這樣子寫

1
2
3
4
5
.indexCard, .orderCard, .carCard {
border: 1px solid #ffffff;
width: 200px;
font-size: 12px;
}

當然這種做法並沒有不好,只是每一次新增你就必須在寫一次,此外也有可能會有人這樣寫,直接統一一種 className

1
2
3
4
5
.carCard {
border: 1px solid #ffffff;
width: 200px;
font-size: 12px;
}

這種做法當然沒有不好,但若拿語意來看就會相當奇怪,我這個頁面明明是清單頁面,為什麼 className 會是購物車?又或者是我明明這裡是首頁,為什麼會是購物車?因此在語義上就非常不好,因此在 SMACSS 中的 Layout 觀念中就會叫你「統一一個抽象名稱」,因此名字就會是一個 l-l 代表著 Layout,並搭配 Card

1
2
3
4
5
.l-card {
border: 1px solid #ffffff;
width: 200px;
font-size: 12px;
}

因此通常 Layout 會有一個前綴詞 l-,透過這種抽象的概念,就可以減少自己在那邊思考 className 的問題,通常只要這個區塊重複性會高達五六成左右,就會將它歸納為 Layout,所以最後總結一下 Layout 的重點在於「抽象語義化命名,抽象出共用樣式」,透過 Layout 你就比較不用在那邊想語義衝突以及語義太詭異的問題。

Module (模組)

在許多框架中都有使用到這個模組化的觀念,舉凡 Boostrap 或是前面所講的 Pure.css 都有使用到這個觀念,因此 SMACSS 中也有這個模組化觀念。

舉例來講,當我們有三個按鈕樣式是這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.btn-blue {
width: 50px;
height: 50px;
padding: 15px;
color: red;
background-color: blue;
}

.btn-white {
width: 50px;
height: 50px;
padding: 15px;
color: red;
background-color: white;
}

.btn-red {
width: 50px;
height: 50px;
padding: 15px;
color: red;
background-color: red;
}

此時我們可以發現這些按鈕除了 background-color 之外,其他都是相同的,那麼我們就可以使用 SMACSS 的 Module 觀念,如果你沒有使用 Module 觀念的話,假使三個按鈕要調整大小或 color 時,你就必須調整三次,因此若套用 SMACSS 的 Module 觀念之後我們可以調整成這樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.btn {
width: 50px;
height: 50px;
padding: 15px;
color: red;
}
.btn-blue {
background-color: blue;
}

.btn-white {
background-color: white;
}

.btn-red {
background-color: red;
}

在這邊 Module 的核心觀念在於「抽出主要的基礎樣式」,因此我們可以將主要的樣式給抽取出來獨立,當下次若要使用時,我們只需要 btn btn-blue,下次若新增別的 class 的時候,就可以減少再次重複撰寫,更不用說若要調整按鈕的時候,就可以一次調整,你可以發現 Module 的概念與 Base 很雷同,但 Base 主要是用於「初始化 HTML 標籤的預設樣式」,所以與 Module 是不同的觀念。

最後這邊要注意一件事情,盡可能 CSS 不要針對 HTML 標籤給予樣式,這樣子會大大減少 CSS 的彈性

1
2
3
4
5
6
.table h2 {
...
}
.list li {
...
}

在 SMACSS 中他會希望你改寫成這樣

1
2
3
4
5
6
.table-title {
...
}
.list-list {
...
}

這樣子才能夠大大增加 CSS 的活用性。

State (狀態)

SMACSS 中的 State 就相對比較簡單一點,舉例來講按鈕可能會有狀態的切換或是一些訊息提示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.is-active {
...
}

.is-error {
...
}

.is-success {
...
}
.is-collapsed {

}

通常狀態都會使用 .is- 當作前綴詞,Status 與 Module 是存在一個非常模糊的關係,他們彼此都是修改現有元素的外觀,但在 SMACSS 中對於 Status 的重點在於

  • 狀態的樣式可以用於任意 Layout 或是 Module
  • 狀態是依賴於 JavaScript 才加入的

此外這邊還有一件很特別的事情 Status 是允許你使用 !important,通常來講你是不會在一個 CSS 上面放入兩個 Status 必定是只有一個 .is-erroris-success,所以除非你的系統非常複雜,否則 !important 基本上用不到。

Theme (主題)

Theme 這個風格使用的機會非常非常的低,就連 SMACSS 官方都說

Theme Rules aren’t as often used

因此這部分若有興趣可以自己看一下官方文件說明就好了。

參考文獻

0%