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で、あらかじめ非表示にしておくところ、そうでないところを指定することができる、という感じです。
いかがでしたでしょうか。どなたかの参考になれたら幸いですー!
このメニューを使ったこんな記事も書きました。
コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。