2011年9月1日

一份重要簡報的導覽

老實說,自從一個規模頗大的官網從手中溜走之後,我很久沒有關心 css 相關的議題了。以前累積下來的CSS知識,這兩三年也讓我輕鬆砍了不少規模中等的網站。但這次,為了處理一個規模相當大的官網切版工作,再加上non-table layout + IE 6 compatible 的要求,我又回來跟CSS裝熟了。

但比較大的問題是:1)設計不是我這邊出的,只能被動收件,而且切第一個版的時候,後面的設計還有一半以上沒出來,2)我以前從來不在乎non-table,最大的擋箭牌就是IE 6。但當客戶舉了業界第一品牌的網站給我看後(馬的,他們的設計比我們簡單一百倍好嗎?)硬著頭皮,只好再度表演特技了。

這三年關於refactor的心得,讓我深信:「do it right once and refactor forever」是千年不變的真理(好拉,其實我也不相信這鬼話),但當我重複在類似的html架構下,寫下近乎完全相同的「border : 1px solid…」時,我就知道事情大條了:CSS中,code duplication的情況太嚴重了,而且,我的refactor沒有unit test做保證。好,那就只能第一次就搞定,不能再想refactor了。因此,我光首頁就重做了三次,第一個內頁就重做了兩次。兩頁花了我一整個星期(一整個星期?C#和AS早就不知道寫到哪了!),還因此每天被人照三餐問候進度….唉…

問題的根源在哪?高中時,跟王浩洋玩prolog的時候,就得到的經驗是: pattern matching rule set 的finite state system,都有難以人工debug的問題,也就無法開發系統(當然,prolog是認為:這個debug的事情,可以由prolog寫成的自動debug系統來做,請各位大笑三聲)。以前我就隱隱覺得CSS selector是個爛東西,但以為是selector跟FP(Functional Programming)比較像的原因;但這次的經驗,讓我確認selector是個更糟糕的東西:他就是pattern matching rule set,而且rule的priority還爛得可怕(specificity和什麼鬼!important)。但,當然也有另一個可能,就是阿拉丁是個爛咖,連html+CSS也寫不好!

前幾天,從http://minipai.tw/post/64看到了http://www.slideshare.net/stubbornella/our-best-practices-are-killing-us這份簡報,讓我確定:我不是爛咖,因為每個人都有這樣的困擾。因為有人說看不懂這份簡報,所以,我決定對這份簡報做個小小的導覽:

--------這是分隔線,以下請配合簡報服用---

簡報一開始到21頁,檢查了許多知名網站的CSS,如facebook等。用數字告訴我們,CSS 的duplication在這些網站中,不停的發生。也就是,這並不是誰的問題,而是我們所有人的問題。

接下來,他用幾頁說明他的觀點:CSS(就像 Javascript一樣)並不糟,問題在於我們用錯工具(好吧,看到第五遍,我承認我有被說服到,但支撐front-end的兩大支柱都被人說爛?恩…)

然後,作者列舉了三個值得討論的best practice,並認為這三個迷思讓大家產生今天的問題:Don’t add any extra elements (不增加額外的tag),Don’t add classes (不要用class),Use descendent selectors exclusively (僅靠單純的tag疊加選擇子達成)。但這三個best practice,導致了specificity快速增加的問題。Specificity是CSS計算rule使用優先順序的規則,meyer 的書解釋得很清楚,又有中文版,大家可以去看一下。

接下來就是一串舉例,告訴我們各種情況下,specificity怎麼快速增加。那個 sidebar的例子,相信做過大官網切版的人,都會感同身受。最後,這樣寫css的方式,會讓我們只能靠firebug或其他類似工具才能確認我們的css code是否正確。

而且,更可怕的,specificity會因為官網上線後增加功能而繼續往上疊加。有些人認為!important會解決這樣的問題,但不!!important會帶來更多的問題。92頁告訴你這個極致會是怎麼樣糟糕的狀況。

之前都是處理selector,94頁開始看style的內容。這邊舉了一個例子稍微值得解釋一下。前面的#sidebar h3憑空出現,讓整個style都做了新的設定。但#sidebar .collaborators h3的內容,其實跟最原始的h3相同。但在css中,我們只能把h3的定義整個拉到#sidebar .collaborators h3再放一次,因為在css中,我們沒有辦法「中和」#sidebar h3產生的影響。這是為什麼簡報一開始,在這些大網站上,你會看到這麼多重複宣告的原因。

怎麼解決?98頁提了幾個思考點:Add non-semantic elements judiciously (慎重考慮加上非語意的tag,比如div), Keep specificity as low as possible(保持specificity盡量低),Abstract repeating visual patterns (把重複的視覺架構萃取出來),Use specificity to define your architecture (定html架構的時候,要把specificity考慮進去)。

後面舉了facebook的media block為例,說明設計時的條件,和對應的作法。(Facebook我沒那麼熟,不過過一陣子會有案子發生,到時來檢查這個例子)。

109頁,舉了兩個最近不停在我眼前出現的字眼:Sass和Less。簡單講,由於CSS的破爛設計,css duplication是會大量發生的。但如果我們有另外一個語言,本身是dry的,可以產生我們要的破爛CSS。那讓程式去產生破爛CSS,我們人只要維護這個語言寫成的碼就可以了;Sass和Less就是這樣的語言。看起來,Sass已經是大部分web developer的首選了。最近試用了一下Sass,暫時無法評論,得等下次有大案子再說了。

-------------這是分隔線,導覽到此結束,以下是碎碎念

希望這樣的導覽對大家有幫助。最後要協同報告的是:Javascript也很爛,而且也是爛到爆;所以同樣的工作也有人做在javascript身上,就是大家最近常聽到的coffeescript。這一次的CSS探險,讓我確定了一個很重要的事情:不管HTML 5再棒,有Javascript和CSS護身,還有死不知恥的W3C consortium不清楚現實開發狀況,Flash 安啦!

還有一點補充,grid system 960的作者,在http://www.slideshare.net/nathansmith/refresh-okc這份簡報的第50, 51頁,也回應了nicole的觀點。請大家自行參照...

還有,我這次很幸運的完全不知道這三個迷思。所以,我對於該加的div絕不手軟,該用的class絕不少用。雖然還是很多的code duplication,但是最近做了一兩個重要的refactor,都很順利。不過,根本解決之道,應該還是使用Sass或Less這樣的工具。但對於一般的designer來說該怎麼辦?我還真不知道。