jQueryでドロップダウンメニューのサンプル!

jQueryでドロップダウンメニューのサンプル!

今回は、jQueryでドロップダウンメニューのサンプル!実装方法につきまして、実際にサンプルコードを用いて、詳しく記載していこうと思います。

Webサイトのグローバルメニューでよく使われている階層型のドロップダウンメニュー。マウスをのせると下層ページをサブメニューとして表示します。もちろん以前ご紹介いたしましたがCSSのみで作成することも可能ですが、アニメーション効果をつけるにはjQueryを利用するのが便利です。アニメーションとUIとしての操作感を考慮して、作成してみます。

という事で、それでは今回はッ、

  • ・ドロップダウンメニューのサンプルHTMLとCSS
  • ・サンプルjQueryやってしまいがちな間違え!
  • ・ドロップダウンメニューのサンプルjQuery(JavaScript)
  • ・メニューに分かりやすいようアイコンを

上記について記載していこうと思います…。

jQueryでドロップダウンメニューのサンプル!1
サンプルdemoページ

ドロップダウンメニューのサンプルHTMLとCSS

それでは早速HTMLを記述してみます。まずは3階層のメニューのマークアップを記述します。

ドロップダウンメニューのサンプルHTML

サンプルHTML<ul id=”dropdown” class=”clearfix”>
<li><a href=”#”>MENU A</a>
<ul>
<li><a href=”#”><span>MENU A1</span></a>
<ul>
<li><a href=”#”><span>MENU A1-1</span></a></li>
<li><a href=”#”><span>MENU A1-2</span></a></li>
<li><a href=”#”><span>MENU A1-3</span></a></li>
</ul>
</li>
<li><a href=”#”><span>MENU A2</span></a>
<ul>
<li><a href=”#”><span>MENU A2-1</span></a></li>
<li><a href=”#”><span>MENU A2-2</span></a></li>
<li><a href=”#”><span>MENU A2-3</span></a></li>
</ul>
</li>
<li><a href=”#”><span>MENU A3</span></a>
<ul>
<li><a href=”#”><span>MENU A3-1</span></a></li>
<li><a href=”#”><span>MENU A3-2</span></a></li>
<li><a href=”#”><span>MENU A3-3</span></a></li>
</ul>
</li>
</ul>
</li>
<li><a href=”#”>MENU B</a>
<ul>
<li><a href=”#”><span>MENU B1</span></a>
<ul>
<li><a href=”#”><span>MENU B1-1</span></a></li>
<li><a href=”#”><span>MENU B1-2</span></a></li>
<li><a href=”#”><span>MENU B1-3</span></a></li>
</ul>
</li>
<li><a href=”#”><span>MENU B2</span></a>
<ul>
<li><a href=”#”><span>MENU B2-1</span></a></li>
<li><a href=”#”><span>MENU B2-2</span></a></li>
<li><a href=”#”><span>MENU B2-3</span></a></li>
</ul>
</li>
<li><a href=”#”><span>MENU B3</span></a>
<ul>
<li><a href=”#”><span>MENU B3-1</span></a></li>
<li><a href=”#”><span>MENU B3-2</span></a></li>
<li><a href=”#”><span>MENU B3-3</span></a></li>
</ul>
</li>
</ul>
</li>
<li><a href=”#”>MENU C</a>
<ul>
<li><a href=”#”><span>MENU C1</span></a>
<ul>
<li><a href=”#”><span>MENU C1-1</span></a></li>
<li><a href=”#”><span>MENU C1-2</span></a></li>
<li><a href=”#”><span>MENU C1-3</span></a></li>
</ul>
</li>
<li><a href=”#”><span>MENU C2</span></a>
<ul>
<li><a href=”#”><span>MENU C2-1</span></a></li>
<li><a href=”#”><span>MENU C2-2</span></a></li>
<li><a href=”#”><span>MENU C2-3</span></a></li>
</ul>
</li>
<li><a href=”#”><span>MENU C3</span></a>
<ul>
<li><a href=”#”><span>MENU C3-1</span></a></li>
<li><a href=”#”><span>MENU C3-2</span></a></li>
<li><a href=”#”><span>MENU C3-3</span></a></li>
</ul>
</li>
</ul>
</li>
</ul>

HTMLは入れ子にしたリストとしてマークアップ。今回は階層を分かりやすくするために、上位のメニューをMENU A、MENU B、MENU Cとしてあります。それ以下は子階層と孫階層を記述してあります。

特筆する所は、最上位のul要素には#dropdownというidを付けておくことくらいで、あとはシンプルなマークアップです。

※a要素の中にspan要素が内包されている箇所がありますが、これはCSSでスタイリングするために記述しています。jQueryのコードは使用しませんので、省略しても問題ありません。

ドロップダウンメニューのサンプルCSS

続いてCSSを記述してみます。

サンプルCSS

#dropdown > li{
float: left;
width: 130px;
text-align: center;
}
#dropdown > li > a{
height: 52px;
background: url(images/menu_bg.jpg) no-repeat 0 0;
color: #818181;
text-shadow: 0 1px 1px #fff;
line-height: 55px;
}
#dropdown > li:hover > a{
background: url(images/menu_hover_bg.jpg) repeat-x 0 0;
color: #4c5482;
}
#dropdown > li:first-child > a{ background-image: url(images/menu_first_bg.jpg); }
#dropdown > li:first-child:hover > a{ background-image: url(images/menu_first_hover_bg.jpg); }
/* サブ階層 */
#dropdown ul{
position: absolute;
left: -35px;
z-index: 9999;
padding: .5em 0;
width: 200px;
border: 1px solid #bbb;
background-color: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,.3);
}
#dropdown ul a{
padding: 0 1em;
color: #777;
}
#dropdown li ul a span{
display: block;
padding: .5em 0;
border-top: 1px solid #bbb;
}
#dropdown ul li:first-child > a span{ border-top-color: transparent; }
#dropdown ul li:hover{ background: #4c5482; }
#dropdown ul li:hover > a span{
color: #fff;
}
#dropdown ul li:hover > a span,
#dropdown ul li:hover + li > a span{
border-color: transparent;
}
/* 孫階層 */
#dropdown ul ul{
top: -8px;
left: 190px;
}

まずは最上位であるli要素は横並びりすとにして、サブメニューとサブメニューのサブメニューは縦に並べます。また、サブメニューは絶対配置で設置していくため、親となるli要素にはposition:relative、サブメニューとなるul要素にはposition:absoluteを記述しています。またz-indexも忘れすに記述します。

サンプルjQueryやってしまいがちな間違え!

それでは、どういった仕組みで作っていくか記載してみます。

・サブメニューとなるul要素を隠す
・メインのli要素にマウスをのせたら、アニメーションでサブメニューを表示する
・マウスが外れたら、アニメーションを非表示にする

ざっとこんな感じで、さほど難しくなさそうです。

マウスホバーで開閉する仕組みを作る

それでは実際にjQueryでコーディングを記述してみます。要素を隠すにはhide()メソッド、マウスホバーにはhover()メソッドを利用すれば問題なさそうです。また、アニメーションにはslideDown()メソッドやslideUp()、fadeIn()、fadeOut()を利用したコードを記述してみます。

$(function(){
$(“#dropdown ul”).hide();——①
$(“#dropdown li”).hover(function(){——②
$(“> ul:not(:animated)”, this).slideDown(“fast”);
},
function(){——③
$(“> ul”, this).slideUp(“fast”);
});
});

まずは①の部分で、hide()メソッドでサブメニューにあたるul要素を非表示にします。続く②がマウスオーバーの部分、③がマウスが外れたときの処理です。

今回は、stop()メソッドの記述がありませんが、その代り少し変わったセレクタを使っています。

$(“> ul:not(:animated)

:not疑似クラスセレクタは否定を表すセレクタで、その後に続く:animate疑似クラスセレクタは、「アニメーション中」の要素のみを取得できるセレクタです。上記では:notと組み合わせているので、「アニメーション中ではない」ul要素を指定していることになります。このようにすると、アニメーション中の要素には処理が行われない為、アニメーションの繰り返しを防止できます。

また、チャイルドセレクタ「>」が使われています。チャイルドセレクタは、孫以降を含めずに、子要素のみを指定するのに便利なセレクタです。このように指定することにより、マウスをのせたli要素の直下のul要素だけを指定することができます。

上記のサンプルjQueryで一件完成したように見えます。実際にコードを記述してブラウザで確認してみると、何ら問題ないように見えますが、実は、アニメーション中だった場合、他のli要素にマウスをのせても何も処理がされず、マウスが乗っているのにサブメニューが表示されない状況が生まれてしまいます。

stop()メソッドで記述しなおしてみる

それでは、以前紹介した方法のstop()メソッドを使って、記述しなおしてみます。

$(function(){
$(“#dropdown ul”).hide();
$(“#dropdown li”).hover(function(){
$(“> ul”, this).stop.slideDown(“fast”);
},
function(){
$(“> ul”, this).stop.slideUp(“fast”);
});
});

上記のように、stop()メソッドを使い、記述しなおしてもslideDown()メソッドの場合、スライドさせながら表示するメソッドなので、アニメーションをstop()メソッドで止めた時点では、非表示(display:none;)になっていません。なので、途中でスライドが止まってしまうことになります。

また、孫メニューも同様で途中で止まってしまう為、本来であればoverflow:visible;になるはずが、途中で止まってしまいoverflow:hidden;が残ったままになってしまいます。

ドロップダウンメニューのサンプルjQuery(JavaScript)

それでは、ドロップダウンメニューが正しく動作するために、上記のメソッドとは異なるanimate()メソッドで記述しなおしてみます。

animate()メソッドで記述する場合、each()メソッド、条件分岐であるif文、css()メソッドなどを使い記述することになるので、多少複雑になります。

$(function(){
$(“#dropdown li”).each(function(){——①
var subMenu = $(“> ul”, this);——②
var defaultHeight = subMenu.height();——③
$(this).hover(function(){——④
if(subMenu.css(“display”) == “none”)——⑤{
subMenu.slideDown(“fast”, function(){
subMenu.css(“overflow”, “visible”);——⑥
});
} else {——⑦
subMenu.stop().animate({
“height”: defaultHeight
}, “fast”, function(){
subMenu.css(“overflow”, “visible”);
});
}
},
function(){
subMenu.stop().slideUp(“fast”);——⑧
});
});
$(“#dropdown ul”).hide();——⑨
});

間違いやすい例の先ほどのコードと比べますと、少し長く複雑になります。順をおって説明してみます。

①で、全体をeach()メソッドで囲んでいます。each()メソッドは、それそれの・・・という処理をするためのメソッドです。ここでは②、③で、subMenuとdefaltHeightという変数にそれぞれのサブメニューや高さを入れるために、each()が必要になります。

変数subMenuにはサブメニューとなる$(“> ul”, this)が、変数defaultHeightには、サブメニューのデフォルトの高さが代入されています。この高さは、あとでanimate()メソッドで高さを変更させるために利用します。

④空の部分がマウスが乗ったときの処理です。今回はanimate()を使うのですが、⑤ではif文を使って条件分岐をしています。条件はsubMenu.css(“display”) ==”none”となっています。つまり非表示状態になります。この場合は前のサンプルと同じように、slideDown()を使います。

また⑥の部分では、slideDown()のコールバックにcss()メソッドが使われています。slideDown()はアニメーションが終了すれば、overflow:visibleに戻るのですが、今回は保険のような意味合いで記述しています。

続く⑦の部分は、サブメニューのdisplayプロパティがnone以外の場合ですから、アニメーションの途中も含む表示状態ということになります。その場合はstop()メソッドとanimate()メソッドを利用して、事前に取得させておいたdefaultHeightになるように高さをアニメーションさせながら変更します。そしてコールバックには先ほどと同じようにcss()メソッドでoverflow:visibleを指定します。

⑧のコードはマウスが外れたときの処理になります。これは今までのサンプルと同じになります。

最後の⑨のコードは、each()メソッドの外に記述します。これは一番最後に記述します。これを一番初めに記述してしまうと、サブナビゲーションがdisplay:noneになり、③の部分で高さを取得できなくなってしまいます。

これで、jQueryはほぼ完成です。UIパーツはユーザーが操作する部分ですから、色々な状況を考慮してコーディングしていくことが大事なことです。

メニューに分かりやすいようアイコンを

ドロップダウンメニューの機能としてのjQueryのコードは、上記サンプルで完成です。しかしドロップダウンメニューはその性質上、下層メニューは通常非表示になっています。パッと見た感じだと、下層メニューが存在するかどうかが分かりにくいため、アイコンを表示させて階層があることを示したほうが、より使い勝手が良いメニューになることと思います。

また、デザインによっては、吹き出しのように三角形の矢印を付けたりして装飾したい場合もあることと思います。そこで、次のサンプルではアイコン用にspan要素を、吹き出し装飾用にli要素を追加したコードを記載してみます。

jQueryでドロップダウンメニューのサンプル!2

$(function(){
$(“#dropdown li”).each(function(){
var subMenu = $(“> ul”, this);
var defaultHeight = subMenu.height();
$(this).hover(function(){
if(subMenu.css(“display”) == “none”){
subMenu.slideDown(“fast”, function(){
subMenu.css(“overflow”, “visible”);
});
} else {
subMenu.stop().animate({
“height”: defaultHeight
}, “fast”, function(){
subMenu.css(“overflow”, “visible”);
});
}
},
function(){
subMenu.stop().slideUp(“fast”);
});
});
$(“#dropdown li:has(ul) > a”).append(‘<span class=”icon”></span>’);——①
$(“#dropdown ul”).prepend(‘<li class=”balloon-caret”></li>’).hide();——②
});

新たに加えたコードは①と②になります。①から説明します。

アイコンを追加する

append()メソッドを利用して、iconというクラスの付いたspan要素を挿入しています。セレクタは「li:has(ul)」と指定しています。:has疑似クラスセレクタは、子孫に指定したセレクタ(この場合はul)をもっている要素だけに絞り込むことができるセレクタです。

上記のように指定すると、子孫にul要素を持つli要素だけに絞り込むことができます。つまりサブメニューをもっているli要素ということになります。サンプルではチャイルドセレクタも併用して、a要素の中にspan.iconを挿入しています。

挿入されたspan要素<a href=”#”>MENU A<span class=”icon”></span></a>
サンプルCSS

span.icon{
position: absolute;
width: 10px;
height: 10px;
background: url(images/icon.png) no-repeat 0 0;
top: 24px;
right: 20px;
}

吹き出しを追加する

続いて②のコードを説明します。

$(“#dropdown ul”).prepend(‘<li class=”balloon-caret”></li>’).hide();

サブメニューであるul要素を非表示にする際に、prepend()メソッドを利用して、li.balloon-caretを挿入しています。
サンプルではこのli.balloon-caretを、先ほどのiconと同じように装飾用に利用しています。

サンプルCSS

li.balloon-caret{
width: 25px;
height: 13px;
background: url(images/carte-top.png) no-repeat 0 0;
position: absolute;
top: -13px;
left: 87px;
}

今回は、あえてjQueryの説明をするために、アイコンや吹き出しを後から加える方法を記載いたしましたが、デザインが初めから決まっているのであれば、初めにアイコンと吹き出しを用意して、個別にCSSで表示させる方法が良いように思います。

ということで今回は、jQueryでドロップダウンメニューのサンプル!つきまして、サンプルコードを交え記載いたしました。

グローバルナビゲーション、以前投稿した「CSSだけで実装する横並びのプルダウンメニュー」のように、CSSだけで記述する方法もありますが、やはりアニメーションを中心に考えますと、まだまだjQueryも使えることと思います。

個人的には、スマホはCSSでコーディングを行い、PC用はjQuerを採用するかもしれません。またこの場合は、jQueryのif文、条件分岐を使用してPCだけに読みこませる方法を取りことと思います。また、今回は最後に、今回使用しましたjQueryのメソッドの公式サイトのリンクを下記に記載しておきます。分からないメソッドがあれば、公式サイトで調べるのがベストかと思います。

とりあえず、今回はここまで…。

お仕事のご依頼は↓コチラより…、それではまた次回…。

jQuery.com 公式ドキュメント