運用 CSS methodologies 去實現模組化
- 2019 年 10 月 3 日
- 筆記
一、什麼是 CSS methodologies
CSS methodologies
,可以理解成 設計模式,也可以理解成 css 規範,市面使用情況如下圖:
你可能在日常開發中並不會專門花時間去注意和了解 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
– 塊,如 header -
Element
– 子元素,如 塊menu 下的 item -
Modfier
– 狀態,如.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 )獲得更好的效率
-
把上文分別介紹他們的好處列舉在一起對比匯總,發現他們解決的核心問題就是:模組化