天天看點

好程式員web前端教育訓練分享值得參考的css理論:OOCSS、SMACSS與BEM

  好程式員web前端教育訓練分享值得參考的css理論:OOCSS、SMACSS與BEM

最近在The Sass Way裡看到了Modular CSS typography一文,發現文章在開頭部分就提到了OOCSS、 SMACSS、 BEM、這3個詞。“如果還不知道這些是什麼,請先不要繼續看下去”,聯想到作者這樣友好(gāo lěng)的提醒,作為圍觀群衆,自然要有所回應。是以,本文在這裡分别介紹它們。

  OOCSS、SMACSS及BEM都是有關css的方法論(準确地說,其中BEM應該是一個完整的前端開發理論,不僅限于css),可作為實作優秀css架構(css architecture)的指南。

  css易于了解,但應用和維護并不簡單。在各種開發情景下,css都可能成為一個問題點。是以,我們編寫群組織css應認真、用心。

  OOCSS

  OOCSS (Object Oriented CSS),字面意思是面向對象的CSS,是由Nicole Sullivan提出的css理論,其主要的兩個原則是:

  Separate structure and skin(分離結構和主題) Separate container and content(分離容器和内容)

  用一個例子來說明。請看下面這樣的圖文排列:

  本作的主角,帝國北部地方貴族施瓦澤男爵的養子,也是托爾茲士官學校特科班“Ⅶ組”的成員。

  .media{

1.

  padding: 10px;

2.

  }

3.

  .media:after{

4.

  display: table;

5.

  clear: both;

6.

  content: " ";

7.

8.

  .media-image-container{

9.

  float: left;

10.

  margin-right: 10px;

11.

12.

  .media-image{

13.

  display: block;

14.

15.

  .media-body{

16.

  overflow: hidden;

17.

18.

  .media-shadow{

19.

  box-shadow: 1px 1px 3px rgba(0, 0, 0, .5);

20.

  上面這段代碼用media表示了這種圖文排列的頁面元素。如果把構成它的html、css及javascript(如果有)看做一個整體,那就相當于這是一個元件,或者說對象(object)。它可以在站點的任何地方被重用。

  這樣是如何展現OOCSS的兩個原則的呢?

  Separate structure and skin

  分離結構和主題是在于将一些視覺樣式效果(例如background、color)作為單獨的“主題”來應用。在上面的例子中的陰影效果,沒有被直接寫在media的樣式規則内,而是被單獨寫在了一個名為media-shadow的class中。是以,它成為了可選擇、可拆分的主題。如果不需要對應主題,什麼也不要加,如果需要,加上對應的class,就是這樣的思路。

  Separate container and content

  分離容器和内容要求使頁面元素不依賴于其所處位置。在上面的例子中,css的選擇符都很短,無繼承選擇符(例如.header .media { }),是以,這個圖文排列的元件,可以在任何地方使用,且會有一緻的外觀。

  如果需要在特定的地方讓這個元件看起來不一樣一些,繼續為這個元件增加class,将“不一樣的部分”作為可配置的選項。元件的外觀仍不依賴其所處位置。

  操作指南

  可以看出,OOCSS風格的css可以描述為兩點:

  增加class 不使用繼承選擇符

  OOCSS追求元件的複用,其class命名比較抽象,一般不展現具體内容。

  SMACSS

  SMACSS (Scalable & Modular Architecture for CSS),是由Jonathan Snook提出的css理論。其主要原則有3條:

  Categorizing CSS Rules(為css分類) Naming Rules(命名規則) Minimizing the Depth of Applicability(最小化适配深度)

  這些原則分别是什麼意思呢?

  Categorizing CSS Rules

  這一點是SMACSS的核心。SMACSS認為css有5個類别,分别是:

  Base Layout(Major Components) Module(Minor Components) State Theme

  Base Rules, 基礎樣式,描述的是任何場合下,頁面元素的預設外觀。它的定義不會用到class和ID。css reset也屬于此類。

  Layout Rules, 布局樣式。它和後面的Module Rules一同,描述的是頁面中的各類具體元素。元素是有層次級别之分的,Layout Rules屬于較高的一層,它可以作為層級較低的Module Rules元素的容器。左右分欄、栅格系統等都屬于布局樣式。

  Module Rules, 子產品樣式。它可以是一個産品清單,一個導覽列。一般來說,Module Rules定義的元素放置于前面說的Layout Rules元素之内。子產品是獨立的,可以在各種場合重用。

  State Rules, 狀态樣式,描述的是任一進制素在特定狀态下的外觀。例如,一個消息框可能有success和error兩種狀态,導覽列中的任一項都可能有current狀态。

  繼續OOCSS中的例子,下面新增的讓元素不顯示的is-hidden就屬于State Rules:

  ...

  複制代碼

  .is-hidden{

  display: none;

  Theme Rules, 主題樣式,描述了頁面主題外觀,一般是指顔色、背景圖。Theme Rules可以修改前面4個類别的樣式,且應和前面4個類别分離開來(便于切換,也就是“換膚”)。SMACSS的Theme Rules不要求使用單獨的class命名,也就是說,你可以在Module Rules中定義.mod { }然後在Theme Rules中也用.mod { }來定義需要修改的部分。

  Naming Rules

  Naming Rules是說在想class等的命名時,考慮用命名展現樣式對應的類别。

  按照前面5種的劃分,Layout Rules用l-或layout-這樣的字首,例如:.l-header、.l-sidebar。

  Module Rules用子產品本身的命名,例如圖文排列的.media、.media-image。

  State Rules用is-字首,例如:.is-active、.is-hidden。

  Theme Rules如果作為單獨class,用theme-字首,例如.theme-a-background、.theme-a-shadow。

  Base Rules不會用到class和ID,是以标簽選擇符為主的樣式,例如p、a,無需命名。

  命名規則不需要嚴格遵守,可以根據實際情況和自身喜好做其他的約定。記錄自己的約定(寫文檔),然後遵守,就是可行的。

  Minimizing the Depth of Applicability

  字面翻譯是最小化适配深度。通過一個簡單的描述來說明:

  / depth 1 /

  .sidebar ul h3 { }

  / depth 2 /

  .sub-title { }

  上下兩端css的差別在于html和css的耦合度。可以想到,由于上面的樣式規則使用了繼承選擇符,是以對于html的結構實際是有一定依賴的。如果把h3元素搬到另一個位置,就有可能不再具有這些樣式。對應的,下面的樣式規則隻有一個選擇符,是以不依賴于特定html結構,隻要為元素添加class,就可以獲得對應樣式。

  當然,繼承選擇符是有用的,它可以減少因相同命名引發的樣式沖突(常發生于多人協作開發)。但是,我們不應過度使用,在不造成樣式沖突的允許範圍之内,盡可能使用短的、不限定html結構的選擇符。這就是SMACSS的最小化适配深度的意義。

  看起來,這一點和OOCSS的分離容器和内容的原則非常相似。

  主要目标

  SMACSS着力于實作兩個主要目标:

  更語義化的html和css 降低對特定html結構的依賴 BEM

  BEM,即Block, Element, Modifier,是由Yandex(俄羅斯最著名的網際網路企業)的開發團隊提出的前端開發理論。BEM通過Block、Element、Modifier來描述頁面。

  Block是頁面中獨立存在的區塊,可以在不同場合下被重用。每個頁面都可以看做是多個Block組成。

  

  Element是構成Block的元素,隻有在對應Block内部才具有意義,是依賴于Block的存在。

  Modifier是描述Block或Element的屬性或狀态。同一Block或Element可以有多個Modifier。

  這三部分結合在一起,可以展現在class命名上,進而為開發者提供更友好、更有意義的css組織方式。其形式是:

  .block { }

  .block_modifier { }

  .block__element { }

  .block__element_modifier { }

  再回到前面OOCSS的那個圖文排列的例子,對應用BEM的寫法的話就是:

  這樣的寫法的好處是,在class命名上以約定的形式攜帶了更多有用資訊。在多人合作的時候,新接手這個項目的人,也可以很容易從class命名上分辨出來,哪些部分是Block,哪些是對應的Element,哪些是Modifier,并進一步推斷出哪部分html可以獨立使用。

  BEM是完整的前端開發理論,這裡隻是提到了它采用的css的class命名規則。可以看出,BEM的命名規則可以使代碼更易于維護。

  這些理論真的可以應用嗎?

  是的,而且有用。但是,請不要過于樂觀,任一種理論都隻是對解決css編寫、維護問題的一種嘗試,及其經驗總結。就實際具體的項目來說,你可能仍然會遇到困惑。這些理論最重要的是提供了一種思路(即使它們也提供開發模式的代碼庫),你可能不直接應用它們,但應該通過它們認識到,在寫代碼之前,需要多一些思考。

  不直接編寫css而是采用less、sass等預編譯器,也同樣需要合理的代碼編寫群組織方式,因為可以從編譯後得到的css來分析,是以原則是相通的。

  結語

  在整理寫文本之前,我隻初步了解過OOCSS,而對另外2個還沒有印象...(嗯,其實很正常)

  本文的3個理論各有各的風格,沒有孰優孰劣之說,都是在編寫css時值得參考的内容。如果可以,非常推薦自己根據這些理論背後的意圖,想一個适合自己的方法。

繼續閱讀