CSS 壞習慣與最佳實踐 探討命名衝突、!important 濫用與魔法數字解法

me
林彥成
2022-09-11 | 5 min.
文章目錄
  1. 1. 什麼是 CSS 最佳實踐?
  2. 2. CSS 命名問題:如何避免混亂與重複
    1. 2.1. 命名太通用
  3. 3. 樣式重複:運用原子化 CSS 提升重用性
  4. 4. 樣式關係不明確:BEM 命名法解決方案
  5. 5. SCSS 巢狀 BEM:可讀性與搜尋效率的權衡
  6. 6. 屬性設定:變數化與模組化管理
    1. 6.1. 屬性重複:透過 CSS 變數提升維護性
    2. 6.2. 魔法數字:潛藏的 CSS 維護地雷
  7. 7. Specificity:CSS 權重的理解與應用
    1. 7.1. !important:慎用 CSS 權重殺手
    2. 7.2. 多餘的選擇器:簡潔高效的 CSS 選擇器寫法
    3. 7.3. 目標設太廣或太窄:精準控制樣式影響範圍
  8. 8. FAQ:CSS 最佳實踐常見問題
    1. 8.1. Q1:BEM 命名法會讓 class 名稱變得很長,這會影響效能嗎?
    2. 8.2. Q2:我應該全面採用 Tailwind CSS (Utility-First) 嗎?
    3. 8.3. Q3:z-index 到底該怎麼管理才不會打架?

什麼是 CSS 最佳實踐?

CSS 最佳實踐 是一套旨在提升樣式表可維護性、可讀性與執行效能的開發準則。其核心策略包括:使用具備語意的命名規範(如 BEM)以避免樣式衝突、採用 原子化 CSS (Atomic CSS) 提升重用率、嚴格管理 Specificity (權重) 以減少 !important 的濫用,以及透過 CSS 變數 消除難以維護的「魔法數字」。遵循這些原則能防止 CSS 隨著專案規模擴大而變成難以管理的「義大利麵條程式碼」,確保前端架構的長期健康。


CSS 是主掌網頁外表的一個重要角色,但如果撰寫不當,就如同亂化妝一般,不僅影響美觀,更會造成維護上的困擾。本篇 CSS 壞習慣CSS 最佳實踐 指南,將帶您深入探討如何避免常見的 CSS 撰寫問題,並提升開發效率。

CSS 在撰寫上,整體來說是圍繞在處理特異性 SpecificityCSS 權重)這個核心概念。小編接下來在這篇文章會開箱 9 種需要避免的 CSS 壞習慣 寫法,並提供對應的解決方案,幫助您打造更高品質的樣式。

CSS 命名問題:如何避免混亂與重複

首先是來探討萬年難解的 CSS 命名 問題,跟午餐、晚餐吃什麼是同等困難的事情? CSS in JS 某些程度上就是為了解決這個問題而存在的。

不過時間管理大師的命名大概是會把 line 的聯絡人寫到大家都看不出來是誰。

命名太通用

.userPhoto 這個樣式檔在購物網站究竟是買家、賣家、系統管理者,都幾?!

1
2
3
4
.userPhoto {
width: 94px;
height: 87px;
}

解決方式,也許是用組合的方式 <img class="photo buyer__photo" />

1
2
3
4
5
6
7
8
9
10
11
.photo {
}

.buyer__photo {
}

.seller__photo {
}

.admin__photo {
}

樣式重複:運用原子化 CSS 提升重用性

因為命名沒有規範,導致同樣的樣式可能被不同的工程師重複撰寫。這不僅增加了程式碼體積,也提高了維護成本。運用 原子化 CSS 的概念,可以有效提升樣式重用性。

1
2
3
4
5
6
7
8
9
10
11
.container {
background-color: #878787;
max-width: 94.87px;
border: none;
}

.card {
background-color: #878787;
max-width: 94.87px;
border: none;
}

使用 SCSS 可以用 @extend 但產生出來的還是重複的 >.^

1
2
3
4
5
6
7
8
9
.container {
background-color: #878787;
max-width: 94.87px;
border: none;
}

.card {
@extend .container;
}

命名可以規範團隊使用原子化樣式來增加重用性

1
2
3
4
5
6
7
8
9
10
11
.bg-87 {
background-color: #878787;
}

.bordor-none {
border: none;
}

.max-width-9487 {
max-width: 94.87px;
}

樣式關係不明確:BEM 命名法解決方案

在複雜的專案中,CSS 樣式 之間的關係不明確是常見的開發痛點。正常撰寫會像下面,其實單看樣式檔或是單看 HTML 蠻難知道相互關係。透過 BEM 命名法,可以清晰表達樣式之間的層級關係。

1
2
3
4
5
6
7
<div class="sheets">
<h1 class="title"></h1>
<ul class="list">
<li class="item active"><a href="#"></a></li>
<li class="item"><a href="#"></a></li>
</ul>
</div>

透過 BEM 可以看得出來 title 會被 sheets 影響 item 會被 list 影響。

1
2
3
4
5
6
7
<div class="sheets">
<h1 class="sheets__title"></h1>
<ul class="list">
<li class="list__item list__item--active"><a href="#"></a></li>
<li class="list__item"><a href="#"></a></li>
</ul>
</div>

SCSS 巢狀 BEM:可讀性與搜尋效率的權衡

SCSS 巢狀 寫法搭配 BEM 雖然能減少重複的打字,但在搜尋樣式時可能需要多一步驟。

1
2
3
4
5
6
7
8
9
10
11
.list {
display: flex;

&__item {
flex: 0 0 25%;
}

&__item--active {
color: red;
}
}

小編個人偏好這樣比較好搜尋 0.0

1
2
3
4
5
6
7
8
9
10
11
.list {
display: flex;

.list__item {
flex: 0 0 25%;
}

.list__item--active {
color: red;
}
}

屬性設定:變數化與模組化管理

CSS 屬性設定 上如果有使用變數,大家最後都會感謝你。良好的屬性管理是 CSS 最佳實踐 的重要環節。

屬性重複:透過 CSS 變數提升維護性

有好幾個地方都需要將字體顯示為 #878787。比較不好的撰寫方式就是在每個地方都加上 color: #878787;。如果突然需要更換顏色會需要動到很多地方,全部取代可能會出現預期外的錯誤。這時候,透過 CSS 變數 (Custom Properties) 可以大幅提升樣式維護性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#intro {
color: #878787;
font-size: 10px;
}

header {
color: #878787;
font-size: 20px;
background-color: green;
}

#banner {
color: #878787;
font-size: 30px;
background-image: url(images/banner.jpg);
}

更好的作法是將 #878787 設成變數,或是寫成一個獨立的 class .text-color

1
2
3
4
5
6
7
:root {
--color-text: #878787;
}

.text-color {
color: #878787;
}

魔法數字:潛藏的 CSS 維護地雷

不解釋,但小編有時候被趕鴨子上架也是會寫 XDDD。所謂「魔法數字」是指在程式碼中直接使用的、沒有明確解釋的數值。

1
2
3
4
5
6
7
8
.divBug {
position: absolute;
top: 94.87px;
}

.zIndexBug {
z-index: 99999;
}

Specificity:CSS 權重的理解與應用

CSS 最重要的就是在處理 SpecificityCSS 權重)這個問題。

!important:慎用 CSS 權重殺手

有些時候你會想蓋掉前一個卻怎麼樣也蓋不掉這時候就會使用 !important,但如果大家都這樣用,就會變成兩個人掉到水裡請問你要救哪個的問題。!importantCSS 權重 中具有最高的優先級,應當慎用。

!important 的適用情境會適用在寫 Utility 的 CSS,將常用的樣式獨立並確保樣式能覆蓋上去。

1
2
3
4
5
6
7
8
header {
color: #000000;
}

header.intro {
color: #878787 !important;
font-size: 20px;
}

多餘的選擇器:簡潔高效的 CSS 選擇器寫法

每個 class 本來就一定會接著某個 element,所以 h1.big 中的 h1 就是多餘的,只是練習打字並不會有太多的加分效果。簡潔高效的 CSS 選擇器 寫法是 CSS 最佳實踐 的一部分。

As It

1
2
3
4
5
6
7
8
h1.big {
}
ul.nav {
}
a.button {
}
div.header {
}

Should Be

1
2
3
4
5
6
7
8
.big {
}
.nav {
}
.button {
}
.header {
}

目標設太廣或太窄:精準控制樣式影響範圍

在撰寫樣式檔以能夠重用的前提下,應該盡量減少使用 ID 選擇器和標籤選擇器。

若是想要直接全域改 HTML element,那最多就是使用 Reset css 或是其他套用框架幫你正規化。

底下這種影響範圍太大都是不建議的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
section {
display: block;
}

figure {
margin-bottom: 20px;
}

div {
padding: 1em;
}

header {
padding: 1em;
}

ID 則是範圍太小,但若是明確的知道就是只有這個,那也請斟酌的使用,舉例來說 React 的 root element 就蠻適合給 ID 的。

1
2
#onlyOne {
}

FAQ:CSS 最佳實踐常見問題

Q1:BEM 命名法會讓 class 名稱變得很長,這會影響效能嗎?

A:幾乎不會。瀏覽器解析 HTML 和 CSS 的效能主要取決於選擇器的複雜度(如層層嵌套的選擇器),而非 class 名稱的長度。BEM 雖然名稱長,但它鼓勵使用扁平的單一 class 選擇器(如 .block__element),這反而有助於提升渲染效能。

Q2:我應該全面採用 Tailwind CSS (Utility-First) 嗎?

A:Tailwind CSS 是原子化 CSS 的極致實踐,非常適合快速開發與維持樣式一致性。但如果您的專案需要高度客製化的語義化結構,或者團隊習慣傳統的 CSS 分離模式,混合使用或 BEM 也是很好的選擇。重點在於團隊是否能遵守同一套規範。

Q3:z-index 到底該怎麼管理才不會打架?

A:避免隨意設定 9999 這種魔法數字。建議定義一套全域的 z-index 變數系統(如 --z-modal: 1000, --z-dropdown: 100),或者依賴現代瀏覽器的 Stacking Context 原理,透過父層結構來管理層級,而非單純依賴數值大小。


喜歡這篇文章,請幫忙拍拍手喔 🤣