ulリスト + jQueryで作る、開閉するアコーディオンメニュー

連動開閉するアコーディオンメニューというものを作ったので、自分の備忘録として。ページ遷移時に該当部分は開いておく機能(WPの条件分岐にて)もおまけで。
サンプル
三角のアイコン部分が開閉します。閉じている時は右向き、開いている時は下向きになります。他を開くと今開いていた所は一緒に閉じます。
参考サイト
jQuery(+CSS3)で作るアコーディオンメニュー(2段アコーディオン対応)- [jQuery] クリックで開閉するアコーディオンパネル – かちびと.net
こちらを参考にさせていただきました。ありがとうございます!
三角アイコン素材
デモで使ってる画像です。よかったらお使い下さい。簡単な画像ですのでどこにでも使っていただいて構いません。スマホ対応のため、CSSで1/2サイズで表示します。
コード
html
<ul class="accordion"> <li class="current"><a href="#">リスト1</a></li> <li><a href="#">リスト2</a></li> <li class="sub"> <p><span>リスト3</span></p> <ul> <li><a href="#">サブリスト3-1</a></li> <li><a href="#">サブリスト3-2</a></li> <li><a href="#">サブリスト3-3</a></li> </ul> </li> <li class="sub"> <p><span>リスト4</span></p> <ul> <li><a href="#">サブリスト4-1</a></li> <li><a href="#">サブリスト4-2</a></li> <li><a href="#">サブリスト4-3</a></li> </ul> </li> <li><a href="#demo">リスト5</a></li> <li class="sub"> <p><span>リスト6</span></p> <ul> <li><a href="#">サブリスト6-1</a></li> <li><a href="#">サブリスト6-2</a></li> <li><a href="#">サブリスト6-3</a></li> </ul> </li> </ul>
css
ul.accordion{ /* アコーディオンを含むリスト */
width: 150px;
margin: 20px 0;
}
ul.accordion ul{
margin: 2px 0 10px 14px;
display: none; /* アコーディオン非表示 */
}
ul.accordion li{ /* 見出し */
list-style: none;
line-height: 20px;
border-left: 3px #6cf solid;
padding-left:5px;
margin: 5px 0;
color: #333;
}
ul.accordion li a{
color: #333;
text-decoration: none;
}
ul.accordion li a:hover, .over{
color: #666;
text-decoration: underline;
}
ul.accordion li.current{
font-weight: bold;
background-color: #dffcff;
}
ul.accordion li.sub{ /* サブメニュー */
border: none;
padding: 0;
}
ul.accordion li p span{ /* サブメニューの三角アイコン */
background:url(accordion-list1.gif) no-repeat 0 6px;
background-size: 4px 7px;
padding-left: 9px;
}
ul.accordion li p span.open{ /* サブメニューが開いてるとき */
background:url(accordion-list2.gif) no-repeat 0 7px;
background-size: 7px 4px;
padding-left: 12px;
}
マウスホバーしたときに下線が出るようにしています。aタグだけでなく開閉部分のホバーにも下線が出たほうが「押せる」感があるかなと思って.overというクラスを作っています。(21行目)
p:hoverでいけると思ってたらIEでバージョンによってぐぬぬ…!クラス作ってjQuery側で付与してあげる形にしました。
jQuery
<script type="text/javascript">
jQuery(function($) {
$('.accordion p').mouseover(function(){
$(this).addClass('over');
});
$('.accordion p').mouseout(function(){
$(this).removeClass('over');
});
$('.accordion p').click(function(){
if($(this).next('ul').is(':visible')) { //既に開いている場所なら
$(this).next('ul').slideUp(300); //閉じる
$(this).children('span').removeClass('open'); //.openを削除
} else { //閉じている場所なら
$('.accordion ul').slideUp(); //全部閉じる
$('.accordion').find('span').removeClass('open'); //.open全削除
$(this).next('ul').slideDown(300); //開く
$(this).children('span').addClass('open'); //.open付加
}
});
})(jQuery);
</script>
WPでない場合は2行目と20行目は必要ありません。
3~8行までが前述の開閉部分のマウスホバー・アウトで.overというクラスを付けたり消したりしてるところ。
9から19行目がクリック時に開閉するところ。詳しくはコメントアウトに解説を書いておきました。
WordPressでページ遷移時に該当部分を開いておく
デフォルトだと全部閉じていますが、このようにページ遷移した時にカレントのあるところは開いておきたい、という内容。
WPじゃない場合も頑張れば出来そうですが、今回自分で実装したのがWPだったのでメモがてら。固定ページの条件分岐を使います。リスト1, 2, 3…のリンク先が、それぞれ p1, p2, p3… というスラッグの固定ページだとします。
php
<?php $ad = ' class="current"'; ?>
<ul class="accordion">
<li<?php if(is_page('p1')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p1">リスト1</a></li>
<li<?php if(is_page('p2')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p2">リスト2</a></li>
<li class="sub">
<?php if(is_page(array('p3-1','p3-2','p3-3'))): //このページのどれかなら ?>
<p><span class="open">リスト3</span></p>
<ul>
<?php else: //それ以外 ?>
<p><span>リスト3</span></p>
<ul class="hide">
<?php endif; //if終了 ?>
<li<?php if(is_page('p3-1')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p3-1">サブリスト3-1</a></li>
<li<?php if(is_page('p3-2')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p3-2">サブリスト3-2</a></li>
<li<?php if(is_page('p3-3')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p3-3">サブリスト3-3</a></li>
</ul>
</li>
<li class="sub">
<?php if(is_page(array('p4-1','p4-2','p4-3'))): ?>
<p><span class="open">リスト4</span></p>
<ul>
<?php else: ?>
<p><span>リスト4</span></p>
<ul class="hide">
<?php endif; ?>
<li<?php if(is_page('p4-1')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p4-1">サブリスト4-1</a></li>
<li<?php if(is_page('p4-2')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p4-3">サブリスト4-2</a></li>
<li<?php if(is_page('p4-3')){ echo $ad; } ?>><a href="<?php echo home_url('/'); ?>p4-3">サブリスト4-3</a></li>
</ul>
</li>
</ul>
長くなるのでリスト5以降は省略。
まず1行目で$adという変数に class="current"という文字列(頭に空白有)を入れておいて、各リスト部分でis_page('スラッグ名')の判別を行い、該当のページなら$adを出力することで、カレント表示させます。
全部にecho ' class="current"';って書いてもいいんですけどちょっとでも短くなるかなーと思って(;´Д`)
そして、6行目で該当のサブリストのページを全て指定して、これに含まれる場合は
<p><span class="open">リスト3</span></p> <ul>
.openをつけたspanにしておいて、それ意外は
<p><span>リスト3</span></p> <ul class="hide">
.openの無いspanと、ulに.hideというクラスがついたもの。
条件によって、このどちらかが出力されるようにしておきます。
css
先ほど書いたcssでは、
ul.accordion ul{
margin: 2px 0 10px 14px;
display: none; /* アコーディオン非表示 */
}
と、サブリストは特に指定無しで全て非表示になっていたところを、
ul.accordion ul{
margin: 2px 0 10px 14px;
}
ul.accordion ul.hide{
display: none; /* アコーディオン非表示 */
}
.hideというクラスがついたところを非表示にする、というふうに分けておきます。
こうすれば、phpによって出し分けされたhtmlで、あらかじめ非表示にしておくところ、そうでないところを指定することができる、という感じです。
いかがでしたでしょうか。どなたかの参考になれたら幸いですー!
このメニューを使ったこんな記事も書きました。




![[WordPress] BackWPupでMySQLiエラーなら、WP-DBManagerと併用するといいかも](https://ateitexe.com/wp-content/uploads/2013/05/130527eye.jpg)

コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。