基于Web標準的UI組件 — 菜單(2)
UI Components Based on Web Standards - Menu (2)
在本文的第一篇中,,我們了解了一個“完美”的菜單應該具備的可用性和易用性特征,,并且創(chuàng)建了基本的XHTML和CSS代碼,。接下來我們將深入到與菜單相關(guān)的一些高級特性的實現(xiàn)技術(shù)上,,首先是——
指示當前活動菜單項
當用戶點擊某菜單項進入網(wǎng)站相應的欄目,,我們通常會希望這個菜單項表現(xiàn)出與其它菜單項不同的視覺特征,,使用戶明確地了解自己所處的“地點”而不至于在站點中迷路。我一直想不好應該是給這個菜單項一個什么樣的名字,,暫且稱為“當前活動菜單項(Currently Active Menu Item)”吧,,如果你有什么好想法請一定在右邊留言告訴我,謝謝^_^,。
當前活動菜單項對創(chuàng)建良好的用戶體驗具有非常重要的作用,,一個負責任的UI設計師是絕對不會忽視它的。實現(xiàn)的方法至少有兩種:“直接指示”與“自上而下的指示”,。
“直接指示”的方法即直接給當前活動菜單項相對應的li
元素一個適當?shù)?code>class屬性,,再在CSS中為這個class
重載一般菜單項的視覺屬性,使它表現(xiàn)出“獨特”的視覺特征,。說得挺懸忽,,做起來很簡單,我們還是用apache.org的菜單為例,并假設已經(jīng)點擊“DB”項進入了相應的欄目:
<li class="active">
<a title="Database access">DB</a>
</li>
XHTML只要做這么一點小小的改進就可以了,,CSS的改動也不大,,只要增加這么一段:
menu li.active a{
background-color:#E8F3FF;
border:1px solid #05F;
}
查看效果(例9)
“自上而下的指示”并不直接在某個菜單項上指明它特殊的身份,而是先給每個菜單項命名,,再在菜單項的“上級(比如body
元素)”處指明哪個菜單項被選中了(頗有些類似皇帝翻牌選擇當晚“臨幸”的妃子^_^),。
我們拿上篇文章中使用”絕對定位”的那個菜單為例,假設“軟件”項被選中:
<body class="chlSoftware">
<menu>
<li id="miMovie"><a href="/movie/" title="DVDRip">電影</a></li>
<li id="miMusic"><a href="/music/" title="mp3">音樂</a></li>
<li id="miSoftware"><a href="/dl/" title="共享">軟件</a></li>
</menu>
</body>
body
元素的class
設置了當前頁面所處的頻道(欄目),,也就是此處chl前綴的意思——Channel,。根據(jù)這個class
就可以設置“臨幸”的規(guī)矩了……-_-|||
body.chlMovie li#miMovie a,
body.chlMusic li#Music a,
body.chlSoftware li#miSoftware a{
background-color:#E8F3FF;
border:1px solid #05F;
}
查看效果(例10)
可能的情況下我建議使用第二種方式,理由如下:
- 寫后臺程序的時候比較方便,,只需判斷當前所處的欄目給
body
設置class
即可(怎么判斷,?那可不是我的事兒....);
- 擴展性好,,不僅可用于指示當前活動菜單項,,也可以給頁面上的其他元素提供當前狀態(tài)的信息。比如你想讓每個欄目有不一樣的主色調(diào),,知道怎么辦了吧^_^,;
- 當皇帝比較爽……
帶圖標的菜單項
做到現(xiàn)在我們的菜單還都是光禿禿的,某些朋友可能已經(jīng)對Web標準技術(shù)在視覺效果上能走多遠產(chǎn)生懷疑,。下面我們就把圖片引入到菜單的制作中,,先從最簡單的講起——給菜單項加個圖標“”。我們以例9的菜單為基礎(chǔ),,對a
元素的樣式做些小修改:
menu a{
/*定義a為塊級元素,,方便用盒模型屬性定義外觀*/
display:block;
/*定義尺寸*/
width:100%;
height:20px;
/*盒模型風格*/
background-color:#F6F6F6;
border:1px solid #DDD;
/*文字樣式*/
font:11px arial;
text-decoration:none;
/*垂直居中*/
line-height:20px;
/*水平居中*/
text-align:center;
/*文字縮進*/
text-indent:20px;
/*圖標*/
background:#F6F6F6 url(i/arrow.gif) 5% 50% no-repeat;
}
查看效果(例11)
這里有三點需要說明一下:
- 去除文字水平居中后菜單項的文字都緊貼左側(cè)排列,我們需要給圖標留出一定的空間,。常用的方法(也是最容易想到的方法),,就是使用
padding-left
。但這樣會面臨IE的盒模型Bug,,雖然解決起來也很方便,,但總不如用text-indent
來得自然,更何況這樣沒有任何的Bug需要處理,。
- 為什么不把圖標直接用
img
標簽插入到XHTML文檔中,?因為這些圖標僅僅是裝飾作用,它們并不是這個網(wǎng)頁真正的“內(nèi)容”,,所以它們出現(xiàn)在XHTML代碼中是不合適的。另外用背景圖的方式處理也更方便更節(jié)約網(wǎng)絡流量,。反過來說,,如果這個圖標是一個logo,比如Apache HTTP Server那支著名的羽毛,,建議你把它加入到XHTML代碼中(別忘了alt屬性),,因為它是這個網(wǎng)頁真正想要表達的“內(nèi)容”,。
- 關(guān)于如何正確設置背景圖,我這里就不多說了,,請參考小雨的《CSS2.0中文手冊》中background部分,。需要注意的是Opera對背景圖定位有一些怪脾氣,請參考我的另一篇文章,。
背景圖翻轉(zhuǎn)技術(shù)
這又是一個很實用的技術(shù),。當我們對簡單的盒模型風格不滿意的時候,自然會想到使用背景圖來創(chuàng)建更有個性的菜單項,,實現(xiàn)的方法也很簡單,,我們還是在例9的基礎(chǔ)上做修改。
先看看兩張背景圖的效果:
普通狀態(tài)(bk01.gif):
鼠標覆蓋(bk02.gif):
CSS的改動也不大,,我就揀重要的講(開始偷懶了……^_^):
menu a:link,menu a:visited{
background:transparent url(i/bk01.gif) 0 0 no-repeat;
}
menu a:hover,menu a:active{
background:transparent url(i/bk02.gif) 0 0 no-repeat;
}
查看效果(例12)
Yes,,就這么簡單,只要給a
元素的四種狀態(tài)設置相應的背景圖就可以了,。這種辦法足以應付各種古里古怪的菜單,,而且不光可以用在菜單上,任何需要模樣古怪的鏈接的地方都可以用上它,。不過這還不是最完美的方法,,還有更棒的。
我們先把兩張背景圖合成一張(bk03.gif):
再修改CSS(這里只列出修改了的部分):
menu a{
...
background:transparent url(i/bk03.gif) 0 0 no-repeat;
}
menu a:link,menu a:visited{
background:transparent url(i/bk01.gif) 0 0 no-repeat;
}
menu a:hover,menu a:active{
background:transparent url(i/bk02.gif) 0 0 no-repeat;
background-position:0 -21px;
}
查看效果(例13)
看明白了嗎,?事實上只用了一張圖,,當鼠標覆蓋事件產(chǎn)生后把圖的位置向上移動了一段距離,剛好露出下半張圖的紅色背景部分,。這樣做有什么好處嗎,?
- 方便管理背景圖。一個大型網(wǎng)站很可能需要使用幾十上百張背景圖,,把相關(guān)的背景圖合在一起可以極大地方便管理和維護,。
- 與桌面軟件皮膚的制作方式更接近。制定中的CSS3已經(jīng)引入桌面軟件皮膚制作中最基本的“九宮格”技術(shù),,由此網(wǎng)頁UI設計已經(jīng)明顯地呈現(xiàn)出向桌面軟件UI設計靠攏的趨勢,。
- 節(jié)約網(wǎng)絡流量。以上面這個例子為例,,小的背景圖0.47K,,合并后的背景圖0.94K。兩張小圖的體積之和也是0.94K,,這有什么節(jié)約的,?我們知道數(shù)據(jù)是以“IP包”的形式在網(wǎng)絡上傳輸。大部分的IP包都在1K左右,比如我的網(wǎng)站服務器收發(fā)的每個IP包大小為1024字節(jié),。每張圖至少需要一個IP包傳輸,,這么一來兩張小圖就占用了2K的流量,而使用一張大圖只需要1K的流量,。對于中小型網(wǎng)站這點流量的出入并不算什么,,但對于日訪問量上千萬的網(wǎng)站來說,“能省則省”并不僅僅是網(wǎng)絡流量的問題,,而是實實在在的經(jīng)濟問題,,不可不重視。
文字替換技術(shù)
某些時候我們對菜單項的視覺效果會要求得更多,,比如沒有文字純粹是一張圖,,或者使用一種極少見的字體。也許你會說:我知道,,用背景圖片,。沒錯,用上面的“背景圖翻轉(zhuǎn)技術(shù)”你可以實現(xiàn)它,。但是a
元素中的文字呢,?不能讓它繼續(xù)出現(xiàn)在視野中了,這時就需要用到“文字替換技術(shù)”,。
為了方便說明,,拿我最喜歡的“百事”和“樂事”做一個簡單的菜單:
<menu>
<li id="miLays">
<a href="http://www./" title="樂事薯片">Lay‘s</a>
</li>
<li id="miPepsi">
<a href="http://www./" title="百事可樂">Pepsi</a>
</li>
</menu>
然后使用“背景圖翻轉(zhuǎn)技術(shù)”把下面這張圖作為背景。
查看效果(例14),。具體的實現(xiàn)代碼請自己查看源文件,,用到的技術(shù)上面都有提到。
接下來就是重頭戲了:把那兩行帶下劃線的難看文字去掉,。讓我們先想想有哪些辦法可以把元素從頁面上隱去:
display:none
,。好像太厲害了一點,不光把文字隱藏起來,,壓根就找不到可以點的鏈接了……-_-|||
visibility:hidden
,。嗯,文字沒了,,鏈接還在……可惜背景圖也沒了,,槍斃!
好像滅什么辦法了,?再次向大家隆重介紹text-indent
,。看看它是怎么做的(在例14的基礎(chǔ)上修改):
menu a{
...
text-indent:-9999px;
text-decoration:none;
}
查看效果(例15)
OMG,,真佩服第一個想出這法子來的人,。讓文字負縮進9999px,,也就是往左移動9999像素,別告訴我你的顯示器有這么大的分辨率^_^,。后面那個text-decoration:none
是為了防止Firefox出現(xiàn)下劃線(不信你可以拿掉它試試)。
到目前為止IE6,、Firefox和Opera都表現(xiàn)完美,,可是還沒完,你會在IE5下發(fā)現(xiàn)根本找不到可點的地方……原來IE5把鏈接的可點區(qū)域和文字一起往左挪到了-9999px處,,真是麻煩啊-__-|||,。解決的方法倒也不難:用絕對定位(這方法是俺自己找出來的,如有雷同純屬英雄所見略同^_^),。
menu li{
position:relative;
...
}
menu a{
position:absolute;
top:0;
left:0;
...
}
查看效果(例16)
這下大家都滿意了,,這篇文章也到尾聲了……
小結(jié)
這篇文章里提到的大部分技術(shù)和思想不僅僅可以使用在菜單上,比如“背景圖翻轉(zhuǎn)技術(shù)”的使用范圍就相當廣,,如果你剛開始學習Web標準,,不妨親手制作一個菜單,熟悉一下這些常用技術(shù),。如果你已經(jīng)有一些Web標準實踐經(jīng)驗,,請關(guān)注這篇文章中提到的各種思想,相信有助于你理解Web標準的目標與責任,。如果你是經(jīng)驗豐富的高手,,請一定指出這篇文章中的錯誤和不足,我也是邊摸索邊總結(jié),,估計缺陷不會少,。
最后謝謝關(guān)注這篇文章的朋友,空的時候我還會接著寫其他《基于Web標準的UI組件》,。
注:說了這么多還不能滿意你的菜單要求,?那你的菜單還真是有點bt,也許我之前翻譯的一篇文章能幫上忙(這篇文章中還提到另一種文字替換技術(shù),,雖然我覺得不怎么好),。