
本文已經(jīng)發(fā)表于InfoQ中文站,(
充滿Trick的CSS,兩難的選擇)
javaeye的hax最近在他的blog上進行了一場關于如何寫css的討論,其中反思和討論了一些關于基于標準或trick進行設計的選擇問題,這個問題也是David Heinemeier Hansson對于XHTML/CSS/Javascript標準進行RIA開發(fā)話題的一個延展。我們可以從中思考如何在不完美的技術中選擇一條相對完美的技術路線?
討論的起因是淘寶網(wǎng)的UED團隊成員段王爺在他的blog上發(fā)表了一篇關于淘寶網(wǎng)頁面設計上的小技巧(Trick)的介紹,這個技巧是為了讓一些條目之間的分隔線完全使用css生成,不使用多余的class,段王爺還對比了其它三種常見實現(xiàn)方法。實現(xiàn)方法如下:
從很久很久以前開始,類目間的橫線無非都只有三種。
1、背景圖
在a標簽設置一個padding 用寬1px高不等的背景圖來position到右側。
缺點:最后一個還是要用class來隱藏掉背景。
2、符號
在每個a標簽之間用“|”符號來填充。
缺點:html文件變大,文件維護變得很麻煩,而且在html中毫無意義。
3、a標簽右側的boder。
同背景圖一樣,只不過使用border-right來代替。缺點也同上。
其實現(xiàn)有(淘寶的實現(xiàn)方式)是利用ul的overflow:hidden 再將li的margin-left:-1px的做法做出來的。這樣的做法就可以同時避免以上的缺點了。
上面提到的使用border的傳統(tǒng)方式需要在第一或者最后一個元素上面添加class來隱藏border,Realazy也在他的blog中給出了一種不錯的解決方案,他推薦這樣做:
導航項目間的豎線,我們往往通過border或者background來實現(xiàn)。特殊需求是,第一項左邊無豎線或最后一項右邊無豎線。按照一般的編程方法,控制第一項要比控制最后一項容易得多。
區(qū)分第一項的還有一個好處是,CSS有一個:first-child的偽元素(pseudo element)可以讓我們輕而易舉的選擇第一個子元素。遺憾的是,當前全球占有率最高的瀏覽器,IE6,并不支持這個偽元素。我們可以手工給第一個元素加上class然后再定義它。等ie6淘汰之時,就可以放心用 :first-child了,相權衡的話,我覺得給第一項加上class="first"也不失為實用主義做法。
Realazy提出的方案的思路是使用基于標準的css選擇器(selector),這種方法的好處是可以實現(xiàn)完美的內(nèi)容與表現(xiàn)分離。但是現(xiàn)實的問題是并非所有的瀏覽器都基于標準實現(xiàn),這也正是基于標準的RIA開發(fā)面對的最大問題,尤其以CSS和Javascript問題最大。javaeye的hax在他的blog中提出了自己對于這個Trick的不同意見:
因為我覺得這個方法一點也不好。很簡單的一個理由:這只是一個trick,只適合這特殊情況,假設你要換用“-”來分割呢?作為插入分割符號來說,真正合理使用css的,我給一個例子:
li ~ li:before { content:'-'; margin:0.25em; }
優(yōu)點:含義非常清晰,維護性極高。你可以換任何的分隔字符,可以設定字體,可以設定顏色、大小等樣式,甚至可以換用圖片作為分隔。
好了,下面說缺點。唯一的缺點:IE不支持。
hax給出的方案在IE中無法使用,其實對于大部分網(wǎng)站來說這就相當于絕大多數(shù)用戶都無法看到這種表現(xiàn),這就意味著失敗。淘寶UED的小馬提出“實用第一”,從這種觀點上說hax的方案就是不實用的。但是hax提出可以使用Dean Edwards的IE7 Javascript庫:
IE7是一個可以讓IE像標準瀏覽器一樣工作的Javascript庫。它修正了很多CSS問題,讓PNG在IE5和IE6下正常工作。
IE7這個庫動態(tài)的實現(xiàn)了很多IE原本不支持的偽類(Pseudo Classes),讓完全基于標準的css選擇器(使用偽類)成為可能。隨后,hax在他的另外一篇blog“面向未來的CSS實踐”中作了如下設想:
我推崇一種面向未來的CSS實踐。即大膽采用CSS2.1甚至部分CSS3的特性。因為絕大多數(shù)特性,F(xiàn)irefox、Opera、 Safari等都已經(jīng)很好的支持了。MSIE7也改進了許多,將來IE也無疑終究會完全支持CSS2.1。對于目前的IE,除了graceful degradation的方式(實際上整個內(nèi)容樣式分離的原則和良好的CSS設計可以確保這點,比如淘寶以前的“裸體”所體現(xiàn)的),可以考慮通過特定手段來patch之。
在這點上,我必須說,我原來也是一直堅持只用ie6的selector的。是什么改變了我?就是Dean Edwards的IE7!它的出現(xiàn)不僅在于實踐價值——即提供了一個對于IE的補丁,讓開發(fā)者可以直接寫CSS2甚至CSS3。
hax提出的這種方式是比較激進的,他還在“面向未來的CSS實踐”中進一步的描述了通過腳本修正的方式解決IE不支持標準偽類和多class問題的設想,他的核心想法就是讓CSS的開發(fā)可以遵循標準,減少為了優(yōu)雅退化(graceful degradation)而向最低支持(瀏覽器)兼容造成的表達方式限制。但是hax自己也提出了這種思路面臨的尷尬,它舉了table布局的實用性價值為例:
我認為出現(xiàn)這樣諷刺的情況,即遵循標準的人活得比不遵循的人更累,是很有問題的。這種矛盾在我身上存在著,2001年的時候我在某bbs上發(fā)了個貼,大數(shù) table布局之罪,但是過了幾天我又跑上去說table布局在某種情況下也可以用用。 dlee同志貌似到現(xiàn)在也跟我當時一樣。如果你確實認為,table布局從實用主義角度無法被完全否定,那DHH同志采用實用主義的角度來力挺 html/css/js就也有點心虛,那個標題也就顯得帶點任性味道……
“遵循標準的人活得比不遵循的人更累”這句話說出了很多堅持基于標準進行CSS設計的開發(fā)人員的心聲,這其實是實用性和堅持標準之間的一些交換,現(xiàn)實世界中兩個方面如何平衡正是廣大XHTML/CSS/Javascript開發(fā)者需要認真思考的,關鍵的問題,還是目的要明確。盲目的遵循標準,例如很多開發(fā)者著迷于使用div布局代替table,但是卻沒有明確的目標就會迷失,hax這樣評價:
從實用主義角度說,謹慎的table布局也許更簡單,因為它更好的映射到了grid模型上。如果你轉用div/span,標簽是清晰了,但是css是混亂的!這些屬性(css屬性)是分散的,css代碼無法反映整體,無法記錄你的grid 布局意圖!這是為什么我們經(jīng)常說我有一個css trick的原因,它是trick而已,是你達到最終目的的手段,但是你的目的,你的意圖,沒有好好加入文檔的話,那維護起來恐怕也不見得輕松。
table布局 其他css樣式 = 清晰的布局意圖和內(nèi)容的混合體
div容器 css樣式 = 內(nèi)容樣式分離,但是從css代碼中很難看出布局意圖
關于div/css布局還有一些誤區(qū),簡單的把table標簽換成div是沒有意義的(若干層級的div可能比table更糟糕)。實際上我們希望的是語義標簽。
我們應該看到,CSS的意圖是將表現(xiàn)分離。從設計的角度就是實現(xiàn)語義化的html結構,讓html/xhtml盡量只表達純粹的數(shù)據(jù)結構。但是此時css里面的布局意圖是比較難以被記錄的(難以被理解就難以維護,難以重構),有其在充斥了大量Trick的情況下,這正是廣大程序員/設計人員需要解決的,我們是否應該通過不斷地重構來找到這個矛盾的平衡點呢?歡迎大家討論。最后附上淘寶UED團隊的小馬總結的淘寶CSS編程原則:
- 盡量不使用hack
- 盡量不使用ie6不支持的選擇符
能符合這兩個條件的最簡潔的寫法,就是我們的目標。