姚 朋
(承德石油高等專科學(xué)信息中心,河北承德 067000)
用CSS實現(xiàn)下拉菜單,需要解決兩個基本問題。第一個是當(dāng)鼠標(biāo)停留在一級菜單上時,CSS要能夠響應(yīng)這個鼠標(biāo)事件。第二個是在CSS響應(yīng)這個鼠標(biāo)事件的時候,讓原來處于隱藏狀態(tài)的二級子菜單顯示出來。在CSS標(biāo)準(zhǔn)中,:hover這個偽類正好可以響應(yīng)當(dāng)鼠標(biāo)停留在某一網(wǎng)頁元素上時這樣一個鼠標(biāo)事件,于是第一個問題解決了。要通過:hover這個偽類提供的鼠標(biāo)事件進行處理,來顯示二級子菜單,就需要使用CSS包含選擇符了[1]。CSS包含選擇符的功能是可以通過某一網(wǎng)頁元素控制包含在其中網(wǎng)頁元素的樣式。這時,用CSS制作下拉菜單的兩條要素已經(jīng)具備了。因此CSS下拉菜單的基本工作原理就是:通過為一級菜單的網(wǎng)頁元素設(shè)置:hover偽類來觸發(fā)鼠標(biāo)事件,然后在這個事件中利用CSS包含選擇符顯示嵌套在一級菜單元素中的二級子菜單。根據(jù)這個原理,也可以制作出多級CSS下拉菜單。
以上的XHTML代碼(除了IE的條件注釋以外)的結(jié)構(gòu)很簡單,一級菜單容器.menu使用了一個無序列表,每個二級子菜單也使用一個無序列表嵌套在相應(yīng)的一級菜單的列表項之內(nèi),所有代碼符合XHTML的標(biāo)準(zhǔn)。
這段XHTML代碼看起來復(fù)雜的地方是其中的IE條件注釋,引入IE條件注釋,是為了兼容IE6,原因是IE6只支持a:hover偽類,而不支持其它網(wǎng)頁元素的:hover偽類。在國內(nèi),截止2012年3月份,IE6的使用率為22.40%[2],所以盡管它對CSS標(biāo)準(zhǔn)的支持不如現(xiàn)代標(biāo)準(zhǔn)瀏覽器,卻暫時還不能忽視它的存在。IE的條件注釋是微軟從IE5開始引入網(wǎng)頁中的一種非標(biāo)準(zhǔn)邏輯語句,它只能為IE瀏覽器所識別,其它非IE瀏覽器則把它當(dāng)做注釋語句忽略掉,因此可以用它來編寫針對某個版本IE瀏覽器的HTML代碼[3]。因此兼容IE6的方法就只能把二級子菜單嵌套在一個超鏈接之內(nèi),雖然這不符合XHTML標(biāo)準(zhǔn)。但是不能直接把二級子菜單嵌套在原有一級菜單的超鏈接里,而是要通過IE條件注釋為IE6增加一個新的一級菜單的超鏈接,包含在二級子菜單的外面,然后通過絕對定位,覆蓋原有的一級菜單。這樣做既可以兼容IE6,又可以使這段XHTML代碼在現(xiàn)代標(biāo)準(zhǔn)瀏覽器里符合標(biāo)準(zhǔn)。以上IE條件注釋語句的意思是:當(dāng)IE瀏覽器的版本小于IE7的時候,向網(wǎng)頁中添加包含在條件注釋中的XHTML代碼。所添加的這些XHTML代碼的作用包括:1)在二級子菜單容器的無序列表外部添加表格,解決IE6二級子菜單的無序列表的問題。2)把這個表格嵌套進超鏈接里,解決IE6不支持li:hover偽類的問題。3)為超鏈接添加一個div容器,解決超鏈接不能正確顯示和定位的問題。
二級子菜單雖然嵌套在一級菜單的列表項之內(nèi),但其能否正常顯示,相對于一級子菜單的位置是一個關(guān)鍵因素。在現(xiàn)代標(biāo)準(zhǔn)瀏覽器中,只有當(dāng)二級子菜單的頂部邊框與一級菜單的底部邊框緊貼或與一級菜單的底部margin有重合時,鼠標(biāo)在從一級菜單移動到二級子菜單的過程中,二級子菜單才不會消失。其次是二級子菜單容器的無序列表UL必須絕對定位,這樣它就不會占用在文檔流中的當(dāng)前位置,而且還可以浮動顯示在其它內(nèi)容之上。由于二級子菜單的定位父元素是一級菜單,所以一級菜單容器.menu中的li要設(shè)置為相對定位。為了使二級子菜單的頂部邊框正好可以緊貼著一級菜單的底部邊框,需要知道一級菜單的精確高度。根據(jù)盒模型,一級菜單的高度是由其中塊狀顯示的超鏈接的高度決定的,計算結(jié)果是20像素,包括外邊框,也就是margin部分。但在IE瀏覽器中,一級菜單的實際高度是22像素,多了2像素,可以看出IE瀏覽器并沒有嚴(yán)格按照盒模型來計算。絕對定位二級子菜單與父元素頂部的距離為21像素,使二級子菜單的頂部邊框緊貼著一級菜單的底部邊框。
默認(rèn)狀態(tài)下,在一級菜單的鼠標(biāo)事件沒有被觸發(fā)的時候,二級子菜單處于隱藏狀態(tài),即設(shè)置visibility:hidden屬性。當(dāng)鼠標(biāo)停留在某個一級菜單上時,對應(yīng)的li:hover偽類響應(yīng)這個鼠標(biāo)事件,通過包含選擇符,設(shè)置其包含的二級子菜單ul的visibility:visible屬性,使二級子菜單顯示出來。由于二級子菜單是嵌套在一級菜單之內(nèi)的,所以當(dāng)鼠標(biāo)離開一級菜單的超鏈接,移動到二級子菜單之上時,二級子菜單仍然會顯示,而當(dāng)鼠標(biāo)移走之后,二級子菜單又會恢復(fù)默認(rèn)的隱藏狀態(tài)。對比用JavaScript實現(xiàn)的下拉菜單,CSS的工作方式就顯得非常的簡潔,從這個例子也可以看出,CSS的某些功能和JavaScript是有重合的。
為了兼容IE6,在XHTML代碼中通過IE條件注釋增加了一些代碼,在CSS中也要對其進行相應(yīng)的控制。第一是把包含一、二級菜單的div容器絕對定位,覆蓋標(biāo)準(zhǔn)瀏覽器下顯示的一級菜單。第二是把嵌套在超鏈接中的表格設(shè)置為內(nèi)聯(lián)顯示,消除表格對IE6中一級菜單高度的影響,使其與現(xiàn)代標(biāo)準(zhǔn)瀏覽器一致。
一級菜單容器.menu類的寬度要顯式定義,否則當(dāng)其實際寬度大于IE和Opera瀏覽器窗口時,會自動換行顯示。一級菜單容器.menu類的高度也要顯式定義,否則Firefox和Opera瀏覽器不能正確解析它與和其后內(nèi)容之間的margin值。根據(jù)盒模型分析這個問題的原因應(yīng)該是:Firefox和Opera沒有根據(jù)一級菜單容器.menu所包含的超鏈接的高度來計算.memu容器的高度,而是直接認(rèn)為它的高度為零,所以其后的內(nèi)容就向上流動,直到被一級菜單擋住,從而導(dǎo)致margin屬性失效。二級子菜單中的列表項或超鏈接不能設(shè)置marign值,否則鼠標(biāo)在經(jīng)過margin區(qū)域時二級子菜單可能會消失。
一般情況下,二級子菜單是緊貼著一級菜單的底邊框顯示的,也可以制作二級子菜單和一級子菜單之間有一定空隙的效果。在現(xiàn)代標(biāo)準(zhǔn)瀏覽器里,這個效果可以很容易的通過一、二級菜單之間的margin值調(diào)節(jié),但是IE6不支持這種方法。為了兼容IE6,可以通過設(shè)置子菜單容器ul的padding-top屬性來調(diào)節(jié)一、二級菜單之間的空隙。但如果希望顯示效果如圖1那樣有一個邊框,就不能直接設(shè)置子菜單容器ul的邊框,而是要通過設(shè)置其內(nèi)部li元素的左右邊框、首個li元素的頂部邊框和末尾li元素的底部邊框來模擬一個邊框。使用padding調(diào)節(jié)一、二級菜單間距的另一個問題是這個距離最大不能超過5像素。
以上介紹的CSS下拉菜單可以兼容國內(nèi)外各種主流的瀏覽器。除了下拉菜單,使用CSS還可以實現(xiàn)選項卡、圖片切換、圓角等很多功能。隨著Web標(biāo)準(zhǔn)化的進程和現(xiàn)代標(biāo)準(zhǔn)瀏覽器對CSS標(biāo)準(zhǔn)更多的支持,CSS將能在網(wǎng)頁中完成更多和更炫目的功能。如今,有越來越多的網(wǎng)頁設(shè)計者開始關(guān)注和研究CSS,將來CSS在網(wǎng)頁設(shè)計中的表現(xiàn)將會更加出色。
[1] 侯利軍.精通Web標(biāo)準(zhǔn)網(wǎng)頁布局—XHTML+CSS+JavaScript[M].北京:人民郵電出版社,2007.
[2] 瀏覽器之家[EB/OL].http://www.liulan7.net/a/top/2012/0402/6547.html.
[3] 朱印宏.CSS商業(yè)網(wǎng)站布局之道[M].北京:清華大學(xué)出版社,2007.