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