多階層対応のドロップダウンメニューへ改造する
サンプル01では1階層までのサブメニューを展開するメニューバーを作成しました。今度はより複雑な構造のサイトでも利用できるように、多階層対応のドロップダウンメニューへ改造します。
HTMLは次のようになります。サンプル01と同じようにul/li要素の入れ子で記述していきます。このサンプルでは、メニューA、Cは1階層目(子カテゴリー)までのサブメニューを、メニューBは2階層目(孫カテゴリー)までのサブメニューを記述しています。
▼サンプル02(HTML部分)
<ul class="menu">
<li><a href="#">メニューA</a>
<ul class="sub">
<li><a href="#">サブメニューA</a></li>
<li><a href="#">サブメニューA</a></li>
<li><a href="#">サブメニューA</a>
<ul class="sub">
<li><a href="#">サブメニューA2</a></li>
<li><a href="#">サブメニューA2</a></li>
<li><a href="#">サブメニューA2</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">メニューB</a>
<ul class="sub">
<li><a href="#">サブメニューB</a></li>
<li><a href="#">サブメニューB</a>
<ul class="sub">
<li><a href="#">サブメニューB2</a></li>
<li><a href="#">サブメニューB2</a></li>
<li><a href="#">サブメニューB2</a>
<ul class="sub">
<li><a href="#">サブメニューB3</a></li>
<li><a href="#">サブメニューB3</a></li>
<li><a href="#">サブメニューB3</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">サブメニューB</a></li>
</ul>
</li>
<li><a href="#">メニューC</a>
<ul class="sub">
<li><a href="#">サブメニューB</a>
<ul class="sub">
<li><a href="#">サブメニューC2</a></li>
<li><a href="#">サブメニューC2</a></li>
<li><a href="#">サブメニューC2</a></li>
</ul>
</li>
<li><a href="#">サブメニューB</a></li>
<li><a href="#">サブメニューB</a></li>
</ul>
</li>
</ul>
CSSは次のようになります。2階層目以降のサブメニューはpositionで表示位置をずらすため、a要素にposition:relative;を設定して表示を位置を合わせるようにしています。サブメニュー内のli要素は(ul.sub li)はfloat:none;を適用して回り込みを解除し、横並びにならないようにしています。
2階層目以降のサブメニュー(ul.sub li ul.sub)はposition:absolute;を指定しています。position:absoluteは、親要素のpositionプロパティにstatic以外の値が設定されている場合、親要素の左上が座標の基準になりますので、top:0;とleft:179px;と設定することで親要素のli要素と横並びに配置できます。この方法なら、階層がいくら増えてもサブメニューがきちんと表示されます。
▼サンプル02(CSS部分)
ul.menu li{
float:left;
width:179px;
height:48px;
background:url("images/btn.png");
position:relative;
}
ul.menu li a{
display:block;
width:100%;
height:100%;
line-height:48px;
text-indent:30px;
font-weight:bold;
color:#CFDFB5;
text-decoration:none;
position:relative;
}
ul.menu li a:hover{
background:url("images/btn_over.png");
}
ul.sub li{
float:none;
}
ul.sub li ul.sub{
position:absolute;
left:179px;
top:0;
}
ul.menu{
zoom:1;
}
ul.menu:after {
height:0;
visibility:hidden;
content:".";
display:block;
clear:both;
}
以上でCSSは完成ですが、残念ながらIE6/IE7にはレイアウト機能にバグがあり、他のブラウザーと表示結果が異なるため、対策用に以下のCSSを追加します。
サブメニュー(ul.sub)にdisplay:none;を設定しているのは、IE6の場合、dispay:noneの要素内の子要素のdisplayプロパティをjQueryで変更できないためです。サンプル01ではスクリプト側で非表示にしていましたが、今回はCSSで非表示しています。
セレクターの冒頭に* htmlを付けているのはIE6用、*+htmlはIE7用のCSSです。IE6/7それぞれのli要素にdisplay:inline;とzoom:1;、サブメニューのul要素に対してposition:relative;とzoom:1;を設定しています。
ul.sub{
display:none;
}
* html ul.menu li{
display:inline;
zoom:1;
}
*+html ul.menu li{
display:inline;
zoom:1;
}
* html ul.sub{
zoom:1;
position:relative;
}
*+html ul.sub{
zoom:1;
position:relative;
}
スクリプト部分は次のようになります。
▼サンプル02(スクリプト部分)
$(function(){
$("ul.menu li").hover(function(){
$(">ul:not(:animated)",this).slideDown("fast")
},
function(){
$(">ul",this).slideUp("fast");
})
})
初期設定はCSSで済ませたので、マウスオーバー/アウトイベントの処理のみ記述しています。サンプル01とほとんど同じですが、子セレクター(関連記事)を利用して、マウスカーソルが重なったli要素の直下のul要素だけ(つまり、子孫カテゴリーが存在する場合だけ)サブメニューの表示/非表示を切り替えるように変更しています。
以上で、多階層型メニューバーが完成しました。slideUp()/slideDownをfadeIn()/fadeOut()(関連記事)に変更するとふわっと表示されるメニューになります。また、背景画像を変更するだけでも簡単にデザインをカスタマイズできます。好みに合わせて動きやデザインを変えてみてください。
著者:西畑一馬(にしはた かずま)

to-R代表、Webクリエイター。PHPによるシステム開発や、CMSを利用したWebサイト制作、SEO対策などのマーケティング、コンサルティング、Webクリエイター向けの講座などを業務で行なっている。また、ブログto-RではJavaScriptやSEO対策、CSS、Movable TypeなどのWeb制作にかかわるさまざまな情報を発信している。
主な著書に「現場のプロから学ぶXHTML+CSS」(共著、毎日コミュニケーションズ刊)がある。
ソーシャルリアクション
この連載の記事
一覧へ
WebPro
jQueryとAjaxで作るスムーズページング
WebデザイナーのためのjQuery入門。jQueryのAjax機能を使ってスムーズなページングを実現する方法をチュートリアルで解説する。