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 . 2 s ease-out; transform: rotate( 135 deg); } #global-nav .sub-menu.is-active > a:after { transform: rotate( -45 deg); } |
シンプルなアコーディオンタイプ
クリックするとサブメニューがアコーディオンが開く、一番オーソドックスなタイプです。
アコーディオンは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 . 2 s 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 . 3 s 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 . 3 s linear; } #sub-nav .sub-menu-nav.is-active { left : 0 ; } |