[譯] 這些 CSS 命名規範將省下你大把除錯時間

unicar發表於2018-01-29

這些 CSS 命名規範將省下你大把除錯時間

[譯] 這些 CSS 命名規範將省下你大把除錯時間

我聽說很多開發者厭惡 CSS。而在我的經驗中,這往往是由於他們並沒有花時間來學習 CSS。

CSS 算不上是最優美的『語言』,但迄今二十多年來,它都是美化 web 舉足輕重的工具。從這點來說,也還算不錯吧?

儘管如此,CSS 寫得越多,你越容易發現一個巨大的弊端。

因為維護 CSS 真是老大難。

特別是那些寫得差勁的 CSS 會很快變成程式設計師的噩夢。

這裡向大家介紹一些命名規範,遵照這些規範可以省時省力,少走彎路。

[譯] 這些 CSS 命名規範將省下你大把除錯時間

對此你一定深有體會吧?

使用連字元分隔的字串

如果你常寫 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 類問題:

  1. 僅從名字就能知道一個 CSS 選擇器具體做什麼
  2. 從名字能大致清楚一個選擇器可以在哪裡使用
  3. 從 CSS 類的名稱可以看出它們之間的聯絡

不知你是否見過這樣的類名:

.nav--secondary {
  ...
}
.nav__header {
  ...
}
複製程式碼

這就是 BEM 命名規範。

向 5 歲小孩解釋 BEM 規範

BEM 規範試圖將整個使用者介面分解成一個個小的可重複使用的元件。

讓我們來看看下圖:

[譯] 這些 CSS 命名規範將省下你大把除錯時間

這可是個足以得獎的火柴人呢 :)

哎,可惜並不是 :(

這個火柴人代表了一個元件,比如說一個設計區塊。

或許你已經猜到了 BEM 這裡的 B 意為『區塊』(‘Block’)。

在實際中,這裡『區塊』可以表示一個網站導航、頁首、頁尾或者其他一些設計區塊。

根據上述解釋,那麼這個元件的理想類名稱即是 stick-man

元件的樣式應寫成這樣:

.stick-man {
  
 }
複製程式碼

在這裡我們使用了連字元分隔法,很好!

[譯] 這些 CSS 命名規範將省下你大把除錯時間

E 代表元素(Elements)

BEM 中的 E 代表著元素。

整體的區塊設計往往並不是孤立的。

比方說,這個火柴人有一個頭部(head),兩隻漂亮的手臂(arms)和雙腳(feet)。

[譯] 這些 CSS 命名規範將省下你大把除錯時間

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. 這些 headfeetarms 都是元件中的元素。它們可視作子元件(child components),也就是父元件的組成部分。 如果使用 BEM 命名規範的話,這些元素的類名都可以通過在兩條下劃線後加上元素名稱來產生。

比如說:

.stick-man__head {
}
.stick-man__arms {
}
.stick-man__feet {
}
複製程式碼

M 代表修飾符(Modifiers)

M 在 BEM 命名法中代表修飾符。

如果說這個火柴人有個 blue 或者 red 這樣的修飾符怎麼辦呢?

[譯] 這些 CSS 命名規範將省下你大把除錯時間

在現實場景裡,這可能是一個 red 或者 blue 的按鈕。這就是之前在講的元件當中的限定修飾。

如果使用 BEM 的話,這些修飾符的類名都可以通過在兩條連字元後加上元素名來產生。

比如說:

.stick-man--blue {
}
.stick-man--red {
}
複製程式碼

最後這個例子展示的是父元件加修飾符。不過這種情況並不經常出現。

假如我們這個火柴人擁有另一個不一樣的頭部大小呢?

[譯] 這些 CSS 命名規範將省下你大把除錯時間

這一次元素被加上了修飾符。記住,元素指一個整體封裝區塊中的一個子元件。

.stick-man 表示區塊(Block), .stick-man__head 表示元素(the element)。

從上例可以看出,雙連字元也可以這樣使用:

.stick-man__head--small {
}
.stick-man__head--big {
}
複製程式碼

重申一次,上例中使用的雙連字元是用來指代修飾符的。

這樣你都明白了吧。

這就是 BEM 的基本用法。

個人來說,我在小專案中一般只用連字元分割法來寫類名,在使用者介面更復雜的專案中使用 BEM 方法。

關於 BEM,從這裡瞭解更多

BEM - Block Element Modifier: _BEM - Block Element Modifier is a methodology, that helps you to achieve reusable components and code sharing in the…_getbem.com

為何要使用命名規範?

在電腦科學當中只有兩類難題:快取失效和命名 - 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 命名規範將省下你大把除錯時間

這裡資料屬性(data attributes)用得很妙。正如這條 Twitter 上所說的。

附加提議:寫更多的 CSS 註釋

這跟命名規範毫無關係,但也能幫你節省時間。

儘管很多 web 開發者儘量不寫 Javascript 評論或者只針對某些情況才寫,但我認為你應該寫更多的 CSS 註釋。

這是因為 CSS 不是最簡潔優雅的『語言』,有條理的註釋可以讓你花更少時間來理解自己的程式碼。

有益無弊,何樂不為。

你可以看看 Bootstrap 的註釋寫得有多好。source code

你倒不需要寫一個 color: red 的註釋告訴自己這是把顏色定為紅色。但如果你用了一個不太簡單明瞭的 CSS 小技巧,這時候大可以寫寫註釋說明一下。

準備好成為 CSS 大牛了麼?

我建立了一本可以讓你 CSS 技能飆升的指南。這裡領取免費電子書

[譯] 這些 CSS 命名規範將省下你大把除錯時間

你不知道的七種 CSS 祕籍。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章