CSS即層疊樣式表,所以一層一層覆蓋其實是其本質特征。真正的問題在於維護,許多人認為CSS僅是樣式,不是代碼,無需維護,所以任意書寫,只要將自己需要的樣式的優先級設為最高即可,才導致了深層級CSS的出現,因為每次添加一個樣式就必須比以前的優先級高才能在頁面看到。深層級不僅造成維護性降低,可讀性也是一個問題,人不是機器,無法很優雅的按優先級閱讀,所以很難確認一個樣式用於哪裡,其實還存在許多的冗余樣式,在任何地方都被覆蓋的樣式。這樣的代碼在擴展性上,一開始反而是有優勢的,因為添加一個新class,無需擔心影響其他地方,但慢慢隨著項目規模的增大,頁面增多,需要復制樣式的地方也越來越多,它們之間又存在微小的差異,設計的更改,需求的變化,這一切都會將這種快餐式的CSS推進柏油坑。因為難以維護,所以無法響應需求,所以無法復用,只能復制,惡性循環。
正如上面所說的,問題在於可讀性、維護性、擴展性、復用性這幾個方面。所以只要提高它們就能解決問題, 雖然這麼說,也不是如此簡單的。先來談談在CSS中,這些概念都有著怎樣的意義。
可讀性
有人認為CSS不是程序,不需要可讀性,有人認為CSS只要寫出來就有可讀性,因為很簡單。拋開各種預處理器不說,原生CSS結構確實簡單,沒有需要編程的部分,但仍然可能導致混亂。原因有二,一是CSS可以層疊,其中涉及到了優先級和作用范圍,如果寫的不好,人很難讀出其中的意義,二是CSS屬性眾多,加上CSS3引入了很多用法獨特的屬性,一個選擇器可能包含幾十個屬性。比如下面這段我隨便寫的CSS代碼:
CSS Code復制內容到剪貼板乍一看也沒什麼,都是border,大致能看出來這段CSS只是為了添加一個紅色的陰影讓box看起來比較立體。但中間的部分似乎是搗亂的,你可能會說這太傻了,看不到嗎。是的,當這3部分散落在上萬行的CSS中時,肯定看不到。於是有人很自然的想起了我們可愛的浏覽器,沒錯,在浏覽器中可以快速找到作用於目標的CSS樣式,但這也是萬惡之源。首先我假設你不知道中間那部分東西是為了什麼而寫的,因為你是靠浏覽器找到它的。然後剩下兩種可能,不管三七二十一改了再說和看看它為什麼存在。前者悲劇的可能性是100%,後者悲劇的可能性是90%,因為你已經掉坑裡了,很快我們會發現要修改它還牽扯到了另外的地方,接著在浏覽器中探索到另一個莫名其妙的樣式,當你弄懂全部的時候,你應該已經把上萬行的代碼弄了個一清二楚了,也許最幸運的是,浪費了幾個小時的時間發現只需要修改一行就能達到目的。
當然,我們可以天真的認為,只要把他們寫在一起就可以了,這樣找起來很簡單。而我將繼續順著這樣的思路來嘗試曝露問題。
維護性
所謂物以類聚是很有道理的,人們習慣將事物歸類,但問題是分類標准,樣式並不關心業務,無論是什麼文字內容,還是功能有何不同,它在乎的只是樣式,比如文字的尺寸,間距和寬高,顏色等等。如果簡單的將一個組件的樣式放在一起,勢必帶來的就是小段代碼的重復書寫。不覺得有多嚴重?我來舉個栗子。
CSS Code復制內容到剪貼板繼續說上面的例子,box需要陰影,但如果這個項目的UI統一風格,包括sidebar,navigator以及item都需要這樣的陰影呢?再如果,明天客戶或者UX一拍腦袋,這個陰影應該是灰色的不該是紅色的呢?不要繼續天真的認為全局替換是救命稻草。首先,沒有幾個網站會用red,blur做色調的,你用的應該是#AA3333,這樣的代碼,然後你發現sidebar用了#A43433,而navigator是#AB3633,等等,item有兩個狀態,而兩個狀態對應的顏色是不一樣的。這怎麼可能?但當你打開浏覽器的時候你會發現本來就相差無幾的顏色,在陰影中變得一模一樣了,誰看的出來呢,當初使用的時候可能也不過是隨意的在mockup中取的一個顏色。
大量的重復帶來的不僅僅是代碼的冗余,我們必須靠人力去同步它們,而人很難保證它們的修改是完全一致的,尤其是當它們中引入了一些不一致的獨特的東西時。不要小看CSS,其後果就是進度和人力的壓力,後面就是PM有沒有讀過《人月神話》的事了。
肯定有人在想,誰讓你當初要寫成這樣呢。我們在讀代碼的時候最喜歡問,當初為什麼要這麼寫?但慢慢的你會讀出它的歷史,有時候它是身不由己的。這就涉及到了下一個要討論的內容。
擴展性
擴展性是一個具有欺騙性的東西,所謂的擴展性其實就是在現有基礎上再次開發新東西的性能,但我認為它還必須有前提條件,那就是保持可讀性與維護性。
簡單的追求可維護性是自取滅亡,原因很簡單,將新舊代碼完全分離的時候擴展性最高,因為不必擔心對以前的部分有影響,新的樣式可以隨意發揮。是不是很神奇,這樣想的我們寫下的代碼,肯定就是前面我們追問的代碼。所以自己回答自己吧,當初沒考慮可讀性和維護性,只想著快點增加新的樣式,就這麼寫了。
那什麼才是一個好的擴展性呢,簡單來說,就是多功能產品。比如一個box,也許它的樣式就時
復用性
似乎我一直在說的就是重復,那我們就來說說復用性,如何才能復用CSS代碼是一個很大的問題,比如粒度,是一兩個屬性進行復用還是一大組選擇器進行復用呢,再比如對象,是為了class復用屬性,還是為了Html復用class呢。這些選擇不算太重要,但是帶來的影響卻很重大,可以說是整個CSS結構的改變。下面繼續用box的陰影來討論復用。
CSS Code復制內容到剪貼板這樣看起來我有了一個shadow的class可以給任意的目標加上這個陰影了,但這導致了一個復用的問題,和上面那段搗亂的CSS樣式一樣,如果item已有另外2個border了,那這個class是無法去除的。所以復用時不僅要考慮需要什麼,還要考慮不需要什麼。另外一些必須的屬性比如display還有overflow等也是要考慮的,因為user agent的原因,很多屬性是隱藏在element中的。