原文鏈接:來自smashing magazine
你是否聽說過一個詞語叫“內容就是王道”?作為一個 Web 開發者,我們的工作與內容創作有着頻繁的聯系。這是一條經常被引用,並且正確地解釋了什么因素吸引了人們訪問網頁的諺語。
然而,從 Web 開發者的角度來看,一些人認為速度就是王道。近年來,許多有經驗的前端工程師已經提出了如何通過最佳實踐來改善用戶體驗的建議。逐漸地,我也開始贊同這個觀點。
不幸地是,當許多開發者們(為了更好的原因)將關注點大量地聚焦於 JavaScript 的性能和其他領域時,CSS 看起來有所被忽略。
在這篇文章里,我會在這個被忽略的領域引入一個新的概念——面向對象的 CSS ,並且闡述它是如何改善你的 Web 頁面性能和可維護性的。
OOCSS 的原則
與任何基於對象的編程方法一樣,OOCSS 的目的是鼓勵代碼復用,使得最終的樣式可以更快地和更有效地添加和維護
正如 OOCSS GitHub repo’s Wiki page 所描述,OOCSS 有兩個主要的原則。
從皮膚分割出結構
在一個有樣式的 Web 頁面里,幾乎每一個元素都有着不同的可見視覺特征(例如“皮膚”),這些特征會重復出現在不同的上下文。想一下一個網站的品牌——顏色,gradients的妙用,又或者可視的邊框。另一方面,其他通常的不可見特征(例如“結構”)同樣是重復出現的。
當這些不同的特征被抽象到基於類的模塊里,它們變得可以被復用並且可以被應用到任何元素,使得元素有着相同的基礎效果。通過對比前后代碼,你就會知道我在討論什么了。
在使用 OOCSS 原則之前,你也許已經有了類似代碼,如下:
#button { width: 200px; height: 50px; padding: 10px; border: solid 1px #ccc; background: linear-gradient(#ccc, #222); box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px; } #box { width: 400px; overflow: hidden; border: solid 1px #ccc; background: linear-gradient(#ccc, #222); box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px; } #widget { width: 500px; min-height: 200px; overflow: auto; border: solid 1px #ccc; background: linear-gradient(#ccc, #222); box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px; }
上面的三個元素都有各自獨特的樣式,並且它們被應用於不可重用的 ID 選擇器來定義樣式。但是它們有着大量通用的樣式。那些通用的樣式也許為了品牌的目的或者設計的一致性。
我們加上一點點計划和考慮,可以把通用樣式抽象出來,使得 CSS 最后變成以下這個樣子:
.button { width: 200px; height: 50px; } .box { width: 400px; overflow: hidden; } .widget { width: 500px; min-height: 200px; overflow: auto; } .skin { border: solid 1px #ccc; background: linear-gradient(#ccc, #222); box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px; }
現在所有的元素都使用類來定義,通用的樣式被結合到一個可復用的 “skin” 類里,這里面沒有東西是不必要的、重復的。我們僅僅需要把 “skin” 類應用到所有的元素,就會得到與第一個例子產生的效果一致,在這里我們先不考慮更少的代碼以及進一步復用的可能性。
容器和內容的分割
在 OOCSS GitHub wiki 頁面上所描述的第二個原則是從內容里分割出容器。為了證明這個原則為什么這么重要,思考以下的 CSS 代碼:
#sidebar h3 { font-family: Arial, Helvetica, sans-serif; font-size: .8em; line-height: 1; color: #777; text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px; }
這樣樣式將會應用在所有 #sidebar
元素下的 h3
子元素。但是,假如我們希望將除了字體大小和文本陰影外的相同樣式應用在 footer 呢?
接下來我們需要做類似事情,如下:
#sidebar h3, #footer h3 { font-family: Arial, Helvetica, sans-serif; font-size: 2em; line-height: 1; color: #777; text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px; } #footer h3 { font-size: 1.5em; text-shadow: rgba(0, 0, 0, .3) 2px 2px 4px; }
或許我們最后做的比上面更糟糕:
#sidebar h3 { font-family: Arial, Helvetica, sans-serif; font-size: 2em; line-height: 1; color: #777; text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px; } /* other styles here.... */ #footer h3 { font-family: Arial, Helvetica, sans-serif; font-size: 1.5em; line-height: 1; color: #777; text-shadow: rgba(0, 0, 0, .3) 2px 2px 4px; }
現在我們使得許多樣式沒有必要地重復,並且根本沒有意識到這個問題(或者簡單來說是我們不在意)。OOCSS 鼓勵我們更多地去思考:在這些不同的元素里有什么是通用的,並且將這些通用的特征分割到模塊或者對象里去,使得它們可以被任何地方復用。
在上面的例子里,那些被聲明使用了子孫選擇器的樣式是不可復用的,因為它們依賴於一個特殊的容器(在這個例子里就是 sidebar
或者 footer
)。
當我們使用 OOCSS 原則下的基於類的模塊建設方法,我們需要確保樣式是不依賴於任何容器元素的。這意味着它們可以不需要理會任何結構上下文,可以在 document 里的任何地方復用。
一個真實案例
為了進一步說明 OOCSS 是如何被使用的,我會使用相似的做法來改善我所做的 my site’s recent redesign 頁面。在編寫完頁面里的內部 header 元素后,我意識到 header 里面的基礎結構樣式是可以被頁面里的其他元素所復用的。
以下幾行是我一開始為我的 header 所寫的樣式:
.header-inside { width: 980px; height: 260px; padding: 20px; margin: 0 auto; position: relative; overflow: hidden; }
在這里的列舉一些樣式對於 .header-inside
元素來說是唯一的。但是剩下的部分可以組成一個復用的模塊。因此我可以抽象出結構樣式到可復用的類里。以下是抽象后的結果:
.globalwidth { width: 980px; margin: 0 auto; position: relative; padding-left: 20px; padding-right: 20px; overflow: hidden; } .header-inside { padding-top: 20px; padding-bottom: 20px; height: 260px; }
屬於 .globalwidth 類的樣式應該遵循以下:
·一個固定的寬度
·居中使用 margin: auto
·為了子元素使用相對定位來創建一個位置上下文
·左右內間距為 20px
·為了 clearfixing 將 overflow 設置為 “hidden”
現在我們無需寫多一行額外的 CSS 代碼,就可以非常自由地使用這些樣式,只需要簡單地通過增加一個類給那些希望有着相同特征的節點即可。
在我的站點里,我復用了這些結構樣式在主要的內容元素以及內部 footer 元素上。根據設計,這些樣式也可以被應用於出現在頁頭和內容之間的水平導航元素,又或者任何一個有着固定寬度以及需要在頁面中居中的元素。
在給這些元素增加 “globalwidth” 樣式后,標記語言就會像以下這樣:
<header> <div class="header-inside globalwidth"> </div> </header> <div class="main globalwidth"> </div> <footer> <div class="footer-inside globalwidth"> </div> </footer>
有些人會覺得這種樣式抽象使得標記變得雜亂,違反了將標記從表現分割的原則。
但是撇開關於這會如何影響標記的爭論,沒有人可以質疑的是,抽象結構化這三個元素令頁面更容易跟蹤和修改常用的樣式。
媒體對象
OOCSS 的先驅之一是 Nicole Sullivan。她創建了一個名為 media object 的項目,她認為這個項目可以節省數百行代碼。
媒體對象是一個展示 OOCSS 能力很好的例子,因為它可以在它的右邊包含任何大小的媒體元素作為內容。盡管許多樣式被應用到媒體對象里面的內容,甚至媒體對象自身大小是可以變化的,但是媒體對象自身通用基礎樣式可以幫助它避免不必要的重復。
OOCSS 的優點
我已經提取了一些 OOCSS 的優點。接下來我會對此展開說明。
更快的網站
OOCSS 帶來的性能優勢是清晰可見的。如果在你的 CSS 代碼里有更少的樣式,這就會使得文件尺寸變小,從而更快地下載資源。
當然,這同樣會使得 HTML 文件變得雜亂並且尺寸變大。但是從許多案例里來看,從樣式表獲取到的性能將會大大彌補標記丟失的性能。
另外一個我們需要記住的概念就是 OOCSS wiki 里提及的“性能贈品”。這是指每次你在 CSS 里復用某些樣式,你就無需使用 CSS 代碼創建新的樣式元素。對於大型、高流量的項目,這些“免費贈品”將成為關鍵的性能收獲。
可維護的樣式表
在自然層疊樣式作為一個重要角色的項目里,使用 OOCSS 使得你無需為樣式表的不斷增長而進行一場特殊的戰斗,它只會讓你有一系列易於維護的模塊。
當為現有的站點添加樣式,在使用 OOCSS 前,你需要考慮在這之前添加到樣式表里的代碼,然后把新的樣式添加到樣式表的底部。使用 OOCSS 后,你只需要復用現有的樣式以及根據現有的規則集進行擴展樣式即可。
在這種思考方式下,有可能使得創建整個頁面只需要編寫極少的 CSS 代碼。任何已經存在的 CSS 模塊都可以作為基礎服務於所有新頁面,並且新的 CSS 代碼將會極小。在某些案例里,你甚至可以無需編寫一行代碼就可以創建一個充滿樣式的頁面。
這些可維護的優勢也會延續到樣式表的健壯性。因為樣式是模塊化的,頁面是基於 OOCSS 構建的,所以當一個新來的開發者開始用使用這些樣式表是不太可能去破壞到這些東西的。
值得注意的點
OOCSS 已經在社區里創建了大量討論,並且引發了一些爭論。在這里,我會嘗試消除一些常見的誤解。
你仍然可以使用 IDs
如果你決定單獨使用 OOCSS 的方式進行工作,你的樣式會大量地基於 CSS 類,並且你不能使用 ID 選擇器給元素加樣式。
正因為此,許多人謊稱 OOCSS 鼓勵人們完全拋棄 IDs 的使用,但這是不正確的。
避免 IDs 的使用,更具體地講是避免使用 IDs 在樣式表的選擇器里。你還需要用 IDs 在你的 HTML 里作為 JavaScript 的鈎子和代碼片段的標識符,因此在 OOCSS 原則里這是完全可以接受的。
當然,有一種情況就是你已經將一個 ID 應用在一個元素上,並且你知道在頁面里這是唯一的。因此你可以通過用 ID 選擇器來捆綁樣式,避免給這個元素增加一個類,從而節省一些字節。但是即使在這個例子里,依靠一個類去實現可以確保未來不會出現特別的問題。
處理較小的項目
對於小型站點和應用,可以肯定的是 OOCSS 會矯枉過正。因此不要在任何環境下都把這篇文章作為 OOCSS 的宣傳,OOCSS 同樣依賴於不同的項目。
盡管如此,至少在你的項目里思考 OOCSS 是一個好主意。一旦你掌握了它,我相信在更大的項目里它會更加容易使用,帶來的優勢也會更加顯著和確切。
實踐的一些指引
開始使用 OOCSS 是需要時間的。我還在研究和探索它,我不會聲稱在這個領域我已經有了所有的答案和經驗。
但是這里有一些你想要的經驗,它們會幫助你進入 OOCSS 的思維模式:
避免使用子孫選擇器(例如:不要用 .sidebar h3)
避免使用 IDs 作為樣式鈎子
避免將類依賴於元素 (例如:不要用 div.header or h1.title)
除了在少數例子里,避免使用 !important
使用 CSS Lint 檢查 CSS 代碼 (你需要知道它有選項以及瘋狂的方法)
使用 CSS grids
顯而易見,在一些時候這些規則是會被打破的,但是總的來說,這些是好的開發習慣,會使得樣式表更小以及更容易去維護。
跟隨 Nicole Sullivan 的工作
如果你想繼續學習 OOCSS,在行業里最需要跟隨的人就是 Nicole Sullivan。
Nicole 除了在她的博客里定時發布文章,還會用幻燈片做大量的展示。以下是一些你想知道的:
-
面向對象的 CSS (Slideshow)
-
高性能網站: Nicole Sullivan (Video)
-
最佳實踐將會殺死我們 (Slideshow)
-
CSS 膨脹 (Slideshow)
結論
許多人害怕 OOCSS 的思想是因為這看起來違反了許多我們所學習的“最佳實踐”,但是一旦長期使用 OOCSS 帶來的有益之處被大家所認識,我確信許多開發者將會轉變他們的思想。
整體來看,我認為 OOCSS 在 CSS 的發展路程中會有一個明亮的未來,它是一個所有開發者都應該結合到項目中的思想——至少,在某個方面,這樣將會使得 Web 頁面更加的快速、高效,以及更加容易維護。