前言
為什么要使用css的編碼規范?
-
編輯一個
class
是否安全,會不會干擾其他 CSS。這是最重要的。 -
想知道一個
class
放在大工程中的什么地方,以防止大腦過載。 -
class
盡可能少,因為看到一長串的class
時會很頭暈。 - 如果一個組件是否使用了 JavaScript,當改變了它的 CSS,不會意外地破壞任何組件。
BEM 和 命名空間 符合諸上所有的標準
什么是 BEM
BEM 是一個規范的總稱縮寫,它代表 block
, element
和 modifier
。當第一次接觸它時,它看起來是那么的難看。但是它很規范。
.block { /* styles */ }
.block__element { /* styles */ }
.block--modifier { /* styles */ }
塊
一個塊就是一個組件。這有點抽象,所以讓我們用示例來學習。
假設您正在建立一個聯系表單。在這種情況下,這個表單可以是一個塊。在 BEM 中,塊被寫為像 class
的名字一樣,如下所示:
.form { /* styles */ }
BEM 使用 .form
而不是 <form>
元素的原因是因為 類允許無限的可重用性,而即使是最基本的元素也可能改變樣式。
按鈕很好地闡釋了可以包含不同樣式的塊。如果將 <button>
元素的背景顏色設置為紅色,則所有 <buttons>
都將被強制繼承紅色背景。接下來,你必須通過覆蓋你的 <button>
元素來修復代碼(并且可能會在修復中“傷及無辜” )。
button {
background-color: red;
}
.something button {
background-color: blue;
}
如果設置了一個 .button
類的按鈕,則可以在任何 <button>
元素上選擇是否使用 .button
類。那么,如果你需要一個不同的背景顏色,你所做的就是改成一個新的 class
,比如說 .button--secondary
,很舒服吧!
.button {
background-color: red;
}
.button--secondary {
background-color: blue;
}
這給我們引入了 BEM 的下一部分 —— 修飾符。
修飾符
修飾符是改變某個塊的外觀的標志。要使用修飾符,可以將 --modifier
添加到塊中。
從上面的按鈕示例繼續,修改的按鈕將被命名為 .button--secondary
。
在傳統的 BEM 中,當你使用修飾符時,你應該 將塊和修飾符添加 到 HTML 中,以便在新的 .button--secondary
中不重寫 .button
樣式。
<button class="button">Primary button</button>
<button class="button button--secondary">Secondary button</button>
.button {
padding: 0.5em 0.75em;
background-color: red;
}
.button--secondary {
background-color: green;
}
注意為什么沒有必要在 .button--secondary
中重新聲明 padding
,因為它已經在 .button
中聲明了。這很棒,因為 BEM 確保你編寫簡潔的 CSS,而不需要付出大量的工作。
但是,我并不喜歡在HTML中再加一個 .button
,因為 .button--modifier
已經告訴我,它是一個帶有 --secondary
標志的 .button
。理想情況下,我的 HTML 應該是這樣的:
<button class="button">Primary button</button>
<button class="button--secondary">Secondary button</button>
這更簡潔,不是嗎?
不幸的是,如果 HTML 中沒有 .button
,我們必須回到非簡潔的 CSS:
.button {
padding: 0.5em 0.75em;
background-color: red;
}
.button--secondary {
padding: 0.5em 0.75em;
background-color: green;
}
呃,這么繁瑣的東西好惡心。 但是有種方法可以編寫簡潔的 CSS,而不需要額外的 class
,那就是使用less、sass中的使用 mixin ,下面是sass的實例:
如果使用 Sass 或任何其他預處理器,則 使用mixin來封裝 需要重用的 所有代碼。在我們的按鈕示例中,我們只需要將 padding
寫入 mixin。 在這里,我在塊中調用這個 mixin:
@mixin button {
padding: 0.5em 0.75em;
}
.button {
@include button;
background-color: red;
}
.button--secondary {
@include button;
background-color: green;
}
元素
元素是塊的子節點。為了表明某個東西是一個元素,你需要在塊名后添加 __element
。所以,如果你看到一個像那樣的名字,比如 form__row
,你將立即知道 .form
塊中有一個 row
元素。
<form class="form" action="">
<div class="form__row">
<!-- ... -->
</div>
</form>
.form__row {
/* styles */
}
BEM 元素有兩個優點 :
- 你可以讓 CSS 的優先級保持相對扁平。
- 你能立即知道哪些東西是一個子元素。
為了解釋以上兩點,考慮使用兩個單獨的 class
的替代方法(許多框架這么做的)。你可能會用這樣的東西:
<form class="form" action="">
<div class="row">
<!-- ... -->
</div>
</form>
.form .row {
/* styles */
}
如果你使用 BEM 元素,則可以使用優先級為 10
而不是 20
的的選擇器來為 .form__row
提供樣式。此外,你可以立即分辨出(不論是在 HTML 還是 CSS 中).form__row
是 .form__row
的子節點。
有一件事你需要了解。永遠不應該鏈式命名 BEM 元素。 如果你的 class
最終像這樣 .form__row__input
,你做的事情是非常錯誤的。
有兩種方法可以繞過長長的 BEM 鏈式命名。 他們是:
- 只把子子元素鏈接到有意義的塊
- 創建新的塊來保存元素
鏈接孫元素到塊
雖然 BEM 建議你將 BEM 元素寫作 .block__element
,但它不會規定你的 HTML 應如何。所以,只要有意義的話,你可以把你的孫元素連在一起。
接下來是一個例子。在下面的代碼中,你將看到 .article__header
是 .article
的子元素。.article__title
是 article
的孫元素(或者說是 .article__header
的子元素,如果你將它們同時表示為 .article
的子元素,就沒有沖突,因為這個表單同時只有他們存在。
<article class="article">
<header class="article__header">
<h1 class="article__title"></h1>
</header>
</article>
雖然這樣有效,你也會遇到無意義的鏈接孫元素的情況。舉個例子:
<section class="comments">
<h2 class="comments__title"></h2>
<article class="comments__comment">
<h3 class="comments__comment-title"></h3>
</article>
<article class="comments__comment">
<h3 class="comments__comment-title"></h3>
</article>
<!-- ... -->
</section>
呃?
此時你需要創建新塊來保存孫元素。
創建新的塊來保存孫元素
在上述情況下,你可以輕松地將 .comments__comment
拆為 .comments
和 .comment
:
<section class="comments">
<h2 class="comments__title"></h2>
<article class="comment">
<h3 class="comment-title"></h3>
</article>
<article class="comment">
<h3 class="comment-title"></h3>
</article>
<!-- ... -->
</section>
這更有意義,不是嗎?如果你這樣做,請確保將 .comments
和 .comment
塊放在同一個文件中,以方便參考。
接下來,還有一件事,在我的用例中添加為 BEM 添加的 —— 命名空間。
命名空間
-
.l-
: 布局(layouts) -
.o-
: 對象(objects) -
.c-
: 組件(components) -
.js
: js的鉤子(JavaScript hooks) -
.is-
|.has-
: 狀態類(state classes) -
.t1
|.s1
: 排版大小(typography sizes) -
.u-
: 實用類(utility classes)著作權歸作者所有。