jQueryのサイドバー固定サブメニュー実装パターン
Posted: 2018.04.27 / Category: javascript / Tag: CSS3, jQuery
最近はモニターのサイズがワイドなってきていることもありサイドバーを固定する機会が増えてきましたね。
そこでjQueryを使用したサイドバー固定にしたときのサブメニューの動きをいくつかご紹介します。
Sponsored Link
基本構造
navの子要素にulでマークアップします。
サブメニューはliの子要素のさらに子要素にulを入れ込みます。
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <aside id="sidebar"> <h1 id="brand-logo">Logo</h1> <nav id="global-nav"> <ul> <li><a href="#">Home</a></li> <li class="sub-menu"> <a href="#">About</a> <ul class="sub-menu-nav"> <li><a href="#">About 1</a></li> <li><a href="#">About 2</a></li> <li><a href="#">About 3</a></li> </ul> </li> <li class="sub-menu"> <a href="#">Products</a> <ul class="sub-menu-nav"> <li><a href="#">Product 1</a></li> <li><a href="#">Product 2</a></li> <li><a href="#">Product 3</a></li> <li><a href="#">Product 4</a></li> </ul> </li> <li> <a href="#">Link</a> <ul class="sub-menu-nav"> <li><a href="#">Link 1</a></li> <li><a href="#">Link 2</a></li> <li><a href="#">Link 3</a></li> </ul> </li> <li><a href="#">Contact</a></li> </ul> </nav></aside> |
サイドバーはposition: fixedで固定になります。
CSS
1 2 3 4 5 6 7 8 9 10 | #sidebar { font-size: 15px; padding: 30px 0; width: 260px; height: 100%; position: fixed; color: #033560; background: #fff; text-align: center;} |
アコーディオンの矢印マークは:after擬似要素で表示します。
is-activeのrotateを変更することアコーディオン開閉時の矢印の向きを制御します。
is-activeクラスを切り替えはJavaScriptで行います。
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #global-nav .sub-menu > a:after { content: ""; position: absolute; top: 0; bottom: 0; right: 18px; margin: auto; vertical-align: middle; width: 8px; height: 8px; border-top: 1px solid #033560; border-right: 1px solid #033560; transition: all .2s ease-out; transform: rotate(135deg);}#global-nav .sub-menu.is-active > a:after { transform: rotate(-45deg);} |
シンプルなアコーディオンタイプ
クリックするとサブメニューがアコーディオンが開く、一番オーソドックスなタイプです。
アコーディオンはCSSでも頑張ればできますが、JSで書いた方がスマートですね。
jQueryのSlideでもいいですが、Velocity.jsというライブラリを使用することでスムーズにアニメーションできます。
is-activeクラスの切り替えは開いたときの矢印の切り替えに使っています。
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <script type="text/javascript">(function($) { $(function () { $('.sub-menu').on('click', function (e) { e.preventDefault(); var $subNav = $('.sub-menu-nav', this); if ($subNav.css("display") === "none") { $(this).addClass('is-active'); $subNav.velocity('slideDown', {duration: 400}); } else { $(this).removeClass('is-active'); $subNav.velocity('slideUp', {duration: 400}); } }); });})(jQuery);</script> |
センターでマウスオーバーアコーディオン
縦センターでマウスオーバーでアコーディオン開くようにするとダイナミックな動きになりますね。
#global-navにdisplay: flexとalign-items: center;で縦方向の中央揃えにできます。
CSS
1 2 3 4 5 6 7 8 9 10 | #global-nav { text-align: center; height: 100%; display: -ms-flex; display: -webkit-flex; display: flex; -ms-flex-align: center; -webkit-align-items: center; align-items: center;} |
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $('.sub-menu').on({ 'mouseenter': function () { $(this) .addClass('is-active') .find('.sub-menu-nav').velocity('slideDown', { duration: 300 }); }, 'mouseleave': function () { $(this) .removeClass('is-active') .find('.sub-menu-nav').velocity('slideUp', { duration: 300 }); }}); |
マウスオーバーでサイドバーの横にスライドで開くタイプ
サブメニューの開閉自体はwdithをCSSのhoverで制御すればできますね。
サブメニューが開いているとき親のメニューもアクティブにするにはJavaScriptでクラスのON/OFFをします。
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #global-nav .sub-menu-nav { position: fixed; background: #033560; color: #fff; top: 0; padding-top: 90px; left: 260px; width: 0; height: 100%; overflow: hidden; transition: width .2s ease-out;}#global-nav .sub-menu:hover .sub-menu-nav { width: 230px;} |
クリックでスライドして切り替わるタイプ
サブメニューが子要素にあるとオーバーフローが上手くいかないので、このパターンだけHTMLの構造を変えています。
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <aside id="sidebar"> <nav id="global-nav"> <ul> <li><a href="#">Home</a></li> <li class="sub-menu"><a href="#">About</a></li> <li class="sub-menu"><a href="#">Products</a></li> <li class="sub-menu"><a href="#">Link</a></li> <li><a href="#">Contact</a></li> </ul> </nav> <div id="sub-nav"> <div id="sub-nav2" class="sub-menu-nav"> <h3 class="sub-menu-head">About</h3> <ul> <li><a href="#">About 1</a></li> <li><a href="#">About 2</a></li> </ul> </div> <div id="sub-nav3" class="sub-menu-nav"> <h3 class="sub-menu-head">Products</h3> <ul> <li><a href="#">Product 1</a></li> <li><a href="#">Product 2</a></li> </ul> </div> <div id="sub-nav4" class="sub-menu-nav"> <h3 class="sub-menu-head">Link</h3> <ul> <li><a href="#">Link 1</a></li> <li><a href="#">Link 2</a></li> </ul> </div> </div></aside> |
JavaScriptではクリック時に#sidebarにis-open-submenuクラスを切り替えることでサブメニューの開閉を行います。
これだけだと全てのサブメニューが表示されてしまうので、表示するサブメニューはis-activeを付与します。
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var $subNav = $('#sub-nav');$('.sub-menu > a').on('click', function (e) { e.preventDefault(); var index = $(this).parent().index() + 1; $subNav.find('#sub-nav' + index).addClass('is-active'); $('#sidebar').addClass('is-open-submenu');});// サブメニューのタイトルをクリックすると閉じる$('.sub-menu-head').on('click', function () { $(this).parent().removeClass('is-active'); $('#sidebar').removeClass('is-open-submenu');}); |
親の#sidebarにoverflow: hiddenを指定します。
CSS
1 2 3 4 5 6 7 8 | #sidebar { width: 260px; height: 100%; position: fixed; color: #fff; background: #033560; overflow: hidden;} |
#global-navと.sub-menu-navをサブメニューが開いているときleftそれぞれ移動させます。
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #global-nav { position: relative; left: 0; transition: left .3s linear;}.is-open-submenu #global-nav { left: -100px;}#sub-nav .sub-menu-nav { position: absolute; top: 0; left: 300px; width: 300px; height: 100%; z-index: 2; transition: left .3s linear;}#sub-nav .sub-menu-nav.is-active { left: 0;} |