運用 CSS methodologies 去實現模組化
一、什麼是 CSS methodologies
CSS methodologies
,可以理解成 設計模式,也可以理解成 css 規範,市面使用情況如下圖:
上圖來源:https://2019.stateofcss.com/technologies/
你可能在日常開發中並不會專門花時間去注意和了解 CSS methodologies,但隨著你經驗的積累,你可能會自己思考,或者閱讀別人的程式碼、參考網上成熟的框架,這裡面都或多或少的蘊含了一些 css methodologies 的閃光點。而下面要介紹的幾種主流的 css methodologies,則可以幫你做到很好的總結和梳理。
二、常見的 CSS methodologies
1、OOCSS
面向物件的 CSS
(Object-Oriented CSS,簡稱 OOCSS
),由 Nicole Sullivan 於 2008 年提出,這基於她在雅虎的工作。
(1)規則
1、不要使用 ID 用 Class
直接使用class來設定樣式,這樣寫不只是可以增加語義,同時也降低css對html的依賴。
2、結構和樣式分離
雖然早期 html 和 css 實現了結構和樣式的分離,但 css 內部同樣存在兩種型別的樣式:
結構樣式(例如長寬、距離)
面板樣式(例如顏色、陰影)
所以 OOCSS 建議把這兩種樣式拆開。
比如有三種按鈕,白色的/綠色的/紅色的,可分別定義為:
class="btn btn-default" class="btn btn-green" class="btn btn-red"
如果你真的有很多個具有紫色按鈕,則可以建立一個單獨的紫色按鈕類。這樣可以大大減少CSS程式碼的數量。
3、容器和內容分離
內容絕不應該限制於特定的容器,為了重用,得分離開。
# 錯誤寫法
.header .action {
}
.header .action .login {
}
.header .action .register {
}
# 正確寫法
.header{
}
.action{
}
.login {
}
.register {
}
繼承選擇符是有用的,它可以減少因相同命名引發的樣式衝突(常發生於多人協作開發)。但是,我們不應過度使用。
(2)利弊
好處:
模組化,可重用
減少程式碼重複
提高可拓展性、可維護性、可讀性
缺點:
雖減少了深層的巢狀選擇器,但是多了更多的類
如果程式碼中沒有大量重複的視覺模式,比如一些小專案,則應用OOCSS可能不切實際
(3)例項
Bootstrap 就是用的 OOCSS。
例如:
html
<div class='header'>
<ul class='menu'>
<li class='menu-item active'>1</li>
<li class='menu-item'>2</li>
<li class='menu-item'>3</li>
</ul>
<div class="action">
<button class="btn btn-login">login</button>
<button class="btn btn-register">register</button>
</div>
</div>
css:
.header {
}
.menu {
}
.menu-item {
}
.item.active {
}
.action {
}
.btn {
}
.btn-login {
}
.btn-register{
}
2、BEM
BEM
- Block Element Modfier(塊元素編輯器)。誕生於2009年。
(1)內容
BEM 包括三個:
Block
- 塊,如 headerElement
- 子元素,如 塊menu 下的 itemModfier
- 狀態,如.current、.active
(2)規則
1、命名規範
-
中劃線 :僅作為連字元使用,表示某個塊或者某個子元素的多單詞之間的連線記號。__
雙下劃線:用來連線塊和塊的子元素。--
雙中劃線:用來描述一個塊或者塊的子元素的一種狀態。在某些公司(如騰訊)的規範裡,雙中劃線被單下劃線(
_
)替代。
例如:.block-name__element--modifier
demo - html:
<div class='header'>
<ul class='header__menu'>
<li class='header__menu-item--active'>1</li>
<li class='header__menu-item'>2</li>
<li class='header__menu-item'>3</li>
</ul>
<div class="header__action">
<button class="header__btn--login">login</button>
<button class="header__btn--register">register</button>
</div>
</div>
demo - less:
.header {
&__menu {}
&__menu-item {}
&__action {}
&__btn {
&--login {}
&--register {}
}
}
2、避免巢狀
BEM 最多隻有 B+E+M 三級。
所以請避免 .block__el1__el2
的格式,直接改為 .block_el2
。
這裡的 block 就很像名稱空間了。
(3)利弊
好處:
層級關係一目瞭然,具有可讀性
不需要依靠層級選擇器來限定約束作用域,可避免跨元件的樣式汙染。
缺點:
命名方式長而難看,書寫不便(可以通過 less/sass 來簡化書寫)
在較小的元件中,BEM 格式可能顯得雞肋。但對於公共的、全域性性的模組樣式定義,還是推薦使用 BEM 格式。(尤其對外發布的公共元件)
其他:
BEM 命名會使得 Class 類名變長,但經過 gzip 壓縮後這個頻寬開銷可以忽略不計。
BEM是不允許用標籤選擇器的,哪怕最簡單的 li 也得寫成 .menu-item。
(4)實踐
餓了麼的框架elementUI就是BEM的一種,或者你也可以研究網站company.yandex.ru/。
3、SMACSS
SMACSS
(Scalable & Modular Architecture CSS ,即 CSS 的可擴充套件性和模組化架構)。Jonathan Snook 於 2011 年提出,當時他在雅虎工作,為 Yahoo Mail 編寫 CSS。
(1)規則
1、Categorizing CSS Rules(CSS 分類規則)
它將 CSS 分為5個不同的類別:
Base
基本規範例如 CSS Reset 和 CSS Normalize。
Layout
佈局規範例如左右分欄、柵格系統。
Module
模組例如一個產品列表,一個導航條。可重用。
State
狀態規範例如選中狀態。
Theme
樣式規範
2、Naming Rules(命名規則)
為類名新增字首
:
- Base 不需要字首。而且是用標籤而不是 class 和 ID。
l-
用作 Layout 的字首:l-inline
m-
用作 Module 的字首:m-callout
。但也可以不用字首。is-
用作 State 的字首:is-collapsed
- Theme 一般會新建個 theme.css,用之前存在的類名。如果想用單獨的類名,可用
theme-
字首。
例子:
<div class="l-box m-profile m-profile--is-pro-user">
<img class="m-avatar m-profile__image" />
<p class="m-profile__bio">...</p>
</div>
(2)例項
線上 demo:https://codepen.io/savemuse/pen/gWVpvd
4、 Atomic CSS
Atomic CSS
也是雅虎提出的,可以從字面意思理解成原子 CSS
。
(1)示例
<div className="P(10px) M(20%) Pos(f) Start(50%) Bgc(#fff)" />
會有專門的 Atomic css 工具,幫助將上面 html 中的 class name 解析成正常的 css。(略)
(2)利弊
好處:將 CSS style 最小元件化,重用性最大化。
壞處:這根本就是在寫 inline-style,只是我們用 class name 的方式來表示而已。
(3)總結
這種做法真的很激進。我暫時無法接受。
三、總結
拋開激進的Atomic,我對剩下的 OOCSS / BEM / SMACSS 有如下建議:
他們各自的思想有互補也有衝突,在實際開發中可以有取捨的使用
他們都可以結合 CSS 前處理器(如 less/sass )獲得更好的效率
把上文分別介紹他們的好處列舉在一起對比彙總,發現他們解決的核心問題就是:模組化