- 原文地址:CSS Naming Conventions that Will Save You Hours of Debugging
- 原文作者:Ohans Emmanuel
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:unicar
- 校對者:dazhi1011,swants
這些 CSS 命名規範將省下你大把除錯時間
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/f13271d0f0c37615438878a41c890921ebfefff40ffe1874a62044c0be125529.png)
我聽說很多開發者厭惡 CSS。而在我的經驗中,這往往是由於他們並沒有花時間來學習 CSS。
CSS 算不上是最優美的『語言』,但迄今二十多年來,它都是美化 web 舉足輕重的工具。從這點來說,也還算不錯吧?
儘管如此,CSS 寫得越多,你越容易發現一個巨大的弊端。
因為維護 CSS 真是老大難。
特別是那些寫得差勁的 CSS 會很快變成程式設計師的噩夢。
這裡向大家介紹一些命名規範,遵照這些規範可以省時省力,少走彎路。
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/910c4642c5ff6b4f9d9212f0f5feb91b70036bfadafaa5d6434ca398a03594d1.jpg)
對此你一定深有體會吧?
使用連字元分隔的字串
如果你常寫 JavaScript,那麼你知道對變數使用駝峰式命名法(camel case)是一種慣例。
var redBox = document.getElementById('...')
複製程式碼
這樣很好,對吧?
但問題是這種命名法並不適用於 CSS。
請切忌以如下方式命名:
.redBox {
border: 1px solid red;
}
複製程式碼
相應的,你可以這樣寫:
.red-box {
border: 1px solid red;
}
複製程式碼
這是一種非常標準的 CSS 命名規範。也可以說更易讀。
同時,這也和 CSS 屬性名稱保持了一致。
// Correct
.some-class {
font-weight: 10em
}
// Wrong
.some-class {
fontWeight: 10em
}
複製程式碼
BEM 命名規範
不一樣的團隊在寫 CSS 選擇器(CSS selectors)有不一樣的方法。有些團隊使用的是連字元分隔(hyphen delimiters)法,還有一些傾向於使用一種叫 BEM 的命名法,這種方法更加有條理。
總的來說,這些 CSS 命名規範試圖解決 3 類問題:
- 僅從名字就能知道一個 CSS 選擇器具體做什麼
- 從名字能大致清楚一個選擇器可以在哪裡使用
- 從 CSS 類的名稱可以看出它們之間的聯絡
不知你是否見過這樣的類名:
.nav--secondary {
...
}
.nav__header {
...
}
複製程式碼
這就是 BEM 命名規範。
向 5 歲小孩解釋 BEM 規範
BEM 規範試圖將整個使用者介面分解成一個個小的可重複使用的元件。
讓我們來看看下圖:
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/a3214b3cb3e236e8b720983d7a8ad49dc0985a7d7a556a387cb8c1a37d64521c.png)
這可是個足以得獎的火柴人呢 :)
哎,可惜並不是 :(
這個火柴人代表了一個元件,比如說一個設計區塊。
或許你已經猜到了 BEM 這裡的 B 意為『區塊』(‘Block’)。
在實際中,這裡『區塊』可以表示一個網站導航、頁首、頁尾或者其他一些設計區塊。
根據上述解釋,那麼這個元件的理想類名稱即是 stick-man
。
元件的樣式應寫成這樣:
.stick-man {
}
複製程式碼
在這裡我們使用了連字元分隔法,很好!
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/c194198f9153ecd5f92c5cc82e54c7479d1777a392757fed72f299021fa1fdcd.png)
E 代表元素(Elements)
BEM 中的 E 代表著元素。
整體的區塊設計往往並不是孤立的。
比方說,這個火柴人有一個頭部(head
),兩隻漂亮的手臂(arms
)和雙腳(feet
)。
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/469da617f26b77e88e8ae0de000e9b7c095f87d796d8f5846de247358ab761d4.png)
The head
, feet
, and arms
are all elements within the component. They may be seen as child components, i.e. children of the overall parent component.
這些 head
、 feet
和 arms
都是元件中的元素。它們可視作子元件(child components),也就是父元件的組成部分。
如果使用 BEM 命名規範的話,這些元素的類名都可以通過在兩條下劃線後加上元素名稱來產生。
比如說:
.stick-man__head {
}
.stick-man__arms {
}
.stick-man__feet {
}
複製程式碼
M 代表修飾符(Modifiers)
M 在 BEM 命名法中代表修飾符。
如果說這個火柴人有個 blue
或者 red
這樣的修飾符怎麼辦呢?
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/7b63e568603565254fefc36cbf1e2d2091217ffc47278563634916c45c9e7a62.png)
在現實場景裡,這可能是一個 red
或者 blue
的按鈕。這就是之前在講的元件當中的限定修飾。
如果使用 BEM 的話,這些修飾符的類名都可以通過在兩條連字元後加上元素名來產生。
比如說:
.stick-man--blue {
}
.stick-man--red {
}
複製程式碼
最後這個例子展示的是父元件加修飾符。不過這種情況並不經常出現。
假如我們這個火柴人擁有另一個不一樣的頭部大小呢?
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/2d7dbceb85149362cda902423730ffbb3f3003f6d9db9e8e585d547e5ab869f5.png)
這一次元素被加上了修飾符。記住,元素指一個整體封裝區塊中的一個子元件。
.stick-man
表示區塊(Block
), .stick-man__head
表示元素(the element)。
從上例可以看出,雙連字元也可以這樣使用:
.stick-man__head--small {
}
.stick-man__head--big {
}
複製程式碼
重申一次,上例中使用的雙連字元是用來指代修飾符的。
這樣你都明白了吧。
這就是 BEM 的基本用法。
個人來說,我在小專案中一般只用連字元分割法來寫類名,在使用者介面更復雜的專案中使用 BEM 方法。
關於 BEM,從這裡瞭解更多
為何要使用命名規範?
在電腦科學當中只有兩類難題:快取失效和命名 - Phil Karlton
命名的確很難。所以我們要儘量把它變得容易點,也為以後維護程式碼省點時間。
能正確命名 CSS 中的類名可以讓你的程式碼變得更易理解和維護。
如果你選擇 BEM 命名規範,在看標記語言(markup)時就更容易看清各個設計元件/區塊之間的關係。
感覺不錯吧?
和 JavaScript 關聯的 CSS 名稱
今天是 John 上班第一天。
他拿到了如下一段 HTML
程式碼:
<div class="siteNavigation">
</div>
複製程式碼
因為剛好讀了這篇文章,John 意識到這種命名方法在 CSS 中不是最好的方法。於是他將程式碼修改成下面這樣:
<div class="site-navigation">
</div>
複製程式碼
看上去不錯吧?
不過 John 沒想到的是,他把整個程式碼庫搞砸了 ???
為什麼會這樣?
在 JavaScript 程式碼中,有一段是和之前的類名 siteNavigation
有關聯的:
// Javascript 程式碼
const nav = document.querySelector('.siteNavigation')
複製程式碼
由於類名的改變,nav
變數現在變成了 null
。
好憂桑。??
為了防止這種情況發生,開發者們想了很多不同的策略。
1. 使用 js- 類名
一種減少這類 bug 的方法是使用 js-
的類名命名方法。用這種方法來表明這個 DOM 元素和 JavaScript 程式碼的關聯。
例如:
<div class="site-navigation js-site-navigation">
</div>
複製程式碼
同樣的在 JavaScript 程式碼中:
//the Javasript code
const nav = document.querySelector('.js-site-navigation')
複製程式碼
依照命名規範,任何人看到 js-
site-navigation
這個類名稱,就會知道 JavaScript 程式碼中有一段和這個 DOM 元素有關聯的程式碼。
2. 使用 Rel 屬性
我自己沒用過這種方法,不過我看到其他人用過。
你是否熟悉這樣的程式碼?
<link rel="stylesheet" type="text/css" href="main.css">
複製程式碼
一般來說,rel 屬性 定義著連結資源和引用它的檔案之間的關係。
回頭看 John 的例子,這種方法建議我們寫成如下的形式:
<div class="site-navigation" rel="js-site-navigation">
</div>
複製程式碼
同時在 JavaScript 中:
const nav = document.querySelector("[rel='js-site-navigation']")
複製程式碼
我對這種方法持保留態度。不過你很可能在某些程式碼庫中看到它們。這種方法就好像在說:“好吧,這裡和 Javascript 有個關聯,那麼我就用 rel 屬性來表示這種關聯。”
網際網路這個地方,解決同一個問題常常有無數種『方法』。
3. 別用資料屬性(data attributes)
有些開發者用資料屬性(data attributes)作為 JavaScript 鉤子。這是不對的。根據定義,data 屬性(data attributes)是用來 儲存自定義資料(to store custom data) 的。
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/96cfe2a8baeb451664cf9b2ec533020b92d0be34c8bbb2ff0d484ce0fa9b745d.png)
這裡資料屬性(data attributes)用得很妙。正如這條 Twitter 上所說的。
附加提議:寫更多的 CSS 註釋
這跟命名規範毫無關係,但也能幫你節省時間。
儘管很多 web 開發者儘量不寫 Javascript 評論或者只針對某些情況才寫,但我認為你應該寫更多的 CSS 註釋。
這是因為 CSS 不是最簡潔優雅的『語言』,有條理的註釋可以讓你花更少時間來理解自己的程式碼。
有益無弊,何樂不為。
你可以看看 Bootstrap 的註釋寫得有多好。source code
你倒不需要寫一個 color: red
的註釋告訴自己這是把顏色定為紅色。但如果你用了一個不太簡單明瞭的 CSS 小技巧,這時候大可以寫寫註釋說明一下。
準備好成為 CSS 大牛了麼?
我建立了一本可以讓你 CSS 技能飆升的指南。這裡領取免費電子書
![[譯] 這些 CSS 命名規範將省下你大把除錯時間](https://i.iter01.com/images/5505834212f846fe72ca5f8d5841aaca6d268ab18bd4de2895cd528c4a39c2ff.png)
你不知道的七種 CSS 祕籍。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。