這部分最後給的成品效果比較驚人,也就是傳說中的純CSS六級選單。這個東西最厲害的地方是相容於所有主流瀏覽器(IE6,IE8,Maxthon2.5,firefox3.5,opera10,safari4與chrome2),而一點CSS hack也沒有用。畢竟CSS hack只是權宜之計,治標不治本,誰知它會對未來新版本的瀏覽器有什麼副作用,因此能不用就不要用了。由於結構非常規律,讀者認真學習後,可以自行擴展為十級菜單。
由於IE6能支援的偽類少得可憐,僅支援a元素的hover與visited與active。為了顯示隱藏的二級選單,我們必須把二級選單的那個無序列表放到a元素下,但這樣一來firefox那邊又發難了。這時我們就要請出IE的條件註釋,讓頁面在IE6下方呈現一套結構層,在其他瀏覽器下方呈現另一套。
<p class="menu"> <ul> <li> <a href="http://www.cnblogs.com/rubylouvre/">菜单三<!--[if !IE 6]><!--></a><![endif]--> <ul> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_11</a></li> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_12</a></li> </ul> <!--[if lte IE 6]></a><![endif]--> </li> <li> <a href="http://www.cnblogs.com/rubylouvre/">菜单二<!--[if !IE 6]><!-->二</a><![endif]--> <ul> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_11</a></li> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_12</a></li> </ul> <!--[if lte IE 6]></a><![endif]--> </li> <li> //************略*********** </li> <li> //************略*********** </li> </ul> </p>
但這樣做不能讓IE6的二級選單彈出來,這情形我在純CSS相簿遇到許多次。查一下國外的資料,說是IE用hover切換絕對定位子元素時有問題,但具體情形又分許多種,解法也不一。但針對多層選單的這種多層子元素,最常用的方法是把它們套在table中,這相當於table佈局。因為table的容錯能力是最強的,這多到人們一直用它來佈局,於是瀏覽器一直在增強它在這方面的優勢。感謝table,我們終於收拾IE6這個怪胎了。
<p class="menu"> <ul> <li> <a href="http://www.cnblogs.com/rubylouvre/">菜单<!--[if !IE 6]><!--><strong>一</strong></a><![endif]--> <table><tr><td> <ul> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_11</a></li> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_12</a></li> </ul> </td></tr></table> <!--[if lte IE 6]></a><![endif]--> </li> <li> <a href="http://www.cnblogs.com/rubylouvre/">菜单<!--[if !IE 6]><!--><strong>二</strong></a><![endif]--> <table><tr><td> <ul> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_11</a></li> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_12</a></li> </ul> </td></tr></table> <!--[if lte IE 6]></a><![endif]--> </li> <li> //*************略************** </li> <li> //*************略************** </li> </ul> </p>
但這樣一來對firefox等瀏覽器添加了許多多餘的結構層程式碼,它們基本上不需要table這東西就能運作良好。因此,我們把table整到IE條件註解中。如:
<p class="menu"> <ul> <li> <a href="http://www.cnblogs.com/rubylouvre/">菜单 <!--[if !IE 6]><!--><strong>一</strong></a><![endif]--> <!--[if lte IE 6]><table><tr><td><![endif]--> <ul> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_11</a></li> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_12</a></li> </ul> <!--[if lte IE 6]></td></tr></table></a><![endif]--> </li> <li> //*************略************ </li> <li> //*************略************ </li> <li> //*************略************ </li> </ul> </p>
然而,這結構層還能進一步精簡。同時我們應該留意到IE6水平選單的異常高度,這是IE6的li元素在包含區塊級顯示元素時會多出5px空隙。由於li元素包含的結構比較複雜,所以以前用對付img元素的幾種方法行不通了。我們可以明確地設定a元素的高度,讓多餘的部分隱藏掉就是。這就唯一不用CSS hack的方法。
更精簡的結構層:
<p class="menu"> <ul> <li> <!--[if lte IE 6]><a href=""><table><tr><td><![endif]--> <a href="http://www.cnblogs.com/rubylouvre/">菜单一</a> <ul> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_11</a></li> <li><a href="http://www.cnblogs.com/rubylouvre/">二级菜单_12</a></li> </ul> <!--[if lte IE 6]></td></tr></table></a><![endif]--> </li> <li> //***********略********* </li> <li> //***********略********* </li> <li> //***********略********* </li> </ul> </p>
.menu a { display:block; /*position:relative;发现放在a元素中, 在标准游览器中惨不忍睹, 和纯CSS相册3的第一个运行框在chrome中遇到的bug一样*/ height:32px; width:100px; line-height:32px; background:#a9ea00; color:#ff8040; text-decoration:none; text-align:center; overflow:hidden;/*★★★★*/ }
基於上面的結構我們就可以開發多層子選單了。
這時我們又發現在IE6下,當我們的滑鼠移到二級選單的上方時,一級選單項目會出現一個邊框,顏色為hover時的背景色。在IE6,table與單元格之間(cellspacing),單元格與單元格的內容之間(cellspadding)是存在空隙,背景色為transparent,也就是說永遠顯示下一層的背景色。由於我們設定a的display:block,它會佔滿td的所有空間,因此那個神秘的邊框應該是cellspacing。我們可以用以下的方式來證實我的猜想。
.menu table { border:1px solid aqua; } .menu table td{ border:1px solid aqua; }
知道問題的所在,我們就可以對症下藥了。解決方法有二。一是設定cellspacing等於零。由於cellspacing為DOM屬性,非CSS屬性,換言之,有多少個table我們就要寫幾次。二是設定border-collapse 為collapse,因為這樣會把table與它裡面的td的border合而為一,這樣它們之間的空隙也不復存在。我們當然選擇第二種啦。
.menu table { border-collapse: collapse; }
#最後總結:
保證hover時,對應的子選單的top與left在包含區塊的範圍內。
通常我們是用hover來呼叫display實現子元素的隱現,但在IE6中,mouseout後它不會乖乖消失,得換visibility上陣。
某些瀏覽器在用a:hover來切換絕對定位子元素存在bug,並統一用li:hover實作。
在IE6中,啟動父級元素的a:hover後再呼叫其子孫元素的a:hover時,會沒有反應,換言之,不繼續向下渲染。這時我們需要table這個容錯能力最強的標籤出馬。
為了跨平台的需要,我們需要用到IE條件註解來切換對應的結構層程式碼。
在IE6中,當li元素包含display為block的元素時(如a)會多出5px,我們可以用overflow:hidden收拾之。
在IE6中,table與td是存在空隙,當我們移動某個子選單項目時,其父選單項目就會因為這些透明的空間而染上兩條邊。解決方法:設定table的border-collapse為collapse。
更多純CSS多層次選單X相關文章請關注PHP中文網!