レスポンシブでハンバーガーメニューになる固定サイドバー

Posted: 2017.09.21 / Category: HTML&CSS, javascript / Tag: jQuery
近年ではモニターサイズが広くなってきた影響もあり、サイドバーを固定表示させてるサイトが多くみられるようになった気がします。
そこでここでは画面が狭くなるとハンバーガメニューになるレスポンシブに対応した固定サイドバーの作成方法をご紹介します。
Sponsored Link
ロゴがナビゲーションに含まれる・マウスオーバーでサブメニュー開閉タイプ

ロゴもサイドバーに含むレイアウトで、サブメニューがある場合はマウスオーバーすると右に表示するタイプです。
HTML
幅を狭めた時にはロゴ部分とメニューは別にしたかったので、構造的に分けてCSSで調節するようにします。
html
<header id="global-head"> <h1 id="brand-logo">Logo</h1> </header> <div id="nav-toggle"> <div> <span></span> <span></span> <span></span> </div> </div> <aside id="sidebar"> <nav id="global-nav"> <ul> <li><a href="#">Home</a></li> <li class="sub-menu"> <a href="#" class="sub-menu-head">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="#" class="sub-menu-head">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> </ul> </li> <li><a href="#">Link</a></li> <li><a href="#">Contact</a></li> </ul> </nav> </aside> <main id="main"> <div id="main-in"> <div id="main-visual"> <h2>Fixed Sidebar</h2> </div> </div><!-- /#main-in --> </main> <div id="overlay"></div>
CSS
CSSは長いので主要部分だけピックアップします。
完全版はサンプルをご覧ください。
css
#global-head { position: fixed; color: #033560; width: 260px; text-align: center; padding-top: 60px; z-index: 100; } #sidebar { font-size: 15px; padding-top: 120px; width: 260px; height: 100%; position: fixed; color: #033560; background: #fff; text-align: center; } #global-nav ul { list-style: none; margin-left: 0; } #global-nav > ul > li { position: relative; } #global-nav a { color: #033560; text-decoration: none; display: block; padding: 15px 0; transition: background-color .3s linear; } /* sub-menu */ #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-nav a, #global-nav .sub-menu:hover .sub-menu-nav { width: 230px; } /* nav-toggle */ #nav-toggle { display: none; position: fixed; top: 15px; right: 15px; height: 32px; } #overlay { display: none; position: fixed; background: rgba(0,0,0,.6); width: 100%; height: 100%; top: 0; left: 0; right: 0; bottom: 0; } @media screen and (max-width: 900px) { #main-in { padding-left: 0; } #global-head { width: 100%; padding: 10px; background: rgba(255,255,255,.8); display: flex; } #sidebar { position: fixed; right: -300px; top: 0; height: 100%; width: 300px; color: #333; background: #fff; transition: .35s ease-in-out; } /* サブメニューは開けない */ #global-nav .sub-menu-head:after, #global-nav .sub-menu-nav { display: none; } #nav-toggle { display: block; } /* nav open */ .open { overflow: hidden; } .open #overlay { display: block; } .open #sidebar { transform: translate3d(-300px,0,0); } /* #nav-toggle close */ .open #nav-toggle span:nth-child(1) { top: 11px; transform: rotate(45deg); } .open #nav-toggle span:nth-child(2) { width: 0; left: 50%; } .open #nav-toggle span:nth-child(3) { top: 11px; transform: rotate(-45deg); } /* z-index */ #overlay { z-index: 200; } #sidebar { z-index: 300; } #nav-toggle { z-index: 400; } }
- 28〜51行目
-
サブメニューはスライドアニメーションで表示させたかったので、
.sub-menu-nav
にはoverflow: hidden;
、直下のaタグにはwidth
を指定してます。
スライドなのでleft
とかでアニメーションさせればよさそうですが、重なりの関係などもあったりするので、.sub-menu-nav
のホーバーでwidth
をアニメーションさせてます。 - 77行目
- ここからは主にタブレット以下のサイズを想定してますので、マウスオーバーで表示していたサブメニューは非表示にしてます。
JavaScript
最後にJavaScriptです。
サブメニューの開閉自体はマウスオーバーなのでCSSでやってるのですが、開いている親のボタンをアクティブにしておきたかったので、そこはjQueryでやってます。
あとはハンバーガーメニューの開閉ですね。
これくらいだったらjQuery入れない選択もありですが、やっぱり楽かなとか。
JavaScript
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script> <script type="text/javascript"> (function($) { $(function () { $('.sub-menu').on({ 'mouseenter': function () { $(this).addClass('is-active'); }, 'mouseleave': function () { $(this).removeClass('is-active'); } }); $('#nav-toggle,#overlay').on('click', function() { $('body').toggleClass('open'); }); }); })(jQuery); </script>
ロゴはコンテンツ側・サブメニューがアコーディオンのタイプ

ヘッダーはコンテンツ側についていて、サブメニューを閉じるとコンテンツ幅が広がって閉じるタイプです。
html
<div id="nav-toggle"> <div> <span></span> <span></span> <span></span> </div> </div> <aside id="sidebar" class="scroll"> <nav id="global-nav"> <ul> <li><a href="#">Home</a></li> <li class="sub-menu"> <a href="#" class="sub-menu-head">About</a> <ul class="sub-menu-nav"> <li><a href="#">About 1</a></li> <li><a href="#">About 2</a></li> </ul> </li> <li class="sub-menu"> <a href="#" class="sub-menu-head">Products</a> <ul class="sub-menu-nav"> <li><a href="#">Product 1</a></li> <li><a href="#">Product 2</a></li> </ul> </li> <li><a href="#">Link</a></li> <li><a href="#">Contact</a></li> </ul> </nav> </aside> <div id="container"> <header id="global-head"> <h1 id="brand-logo">Logo</h1> </header> <main id="main"> <div id="main-visual"> <h2>Fixed Sidebar</h2> </div> <section class="inner"> </section> </main> </div><!-- /#container -->
サブメニューをアコーディオンにする場合は画面にコンテンツ量によっては画面に収まらない可能性がありますので、スクロールバーを入れるのがスタンダードです。
Perfect Scrollbarはバーをいい感じにしてくれます。
あとアコーディオン動作にはVelocity.jsを使用してます。
JavaScript
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.8.1/js/perfect-scrollbar.jquery.min.js"></script> <script type="text/javascript"> (function($) { $(function () { // サイドサブメニューアコーディオン $('.sub-menu-head').on('click', function(){ var $subNav = $(this).next('.sub-menu-nav'); if ($subNav.is(':visible')) { $subNav.velocity('slideUp', {duration: 200}); $(this).parent('li').removeClass('is-active'); } else { $subNav.velocity('slideDown', {duration: 200}); $(this).parent('li').addClass('is-active'); } return false; }); $('#nav-toggle').on('click', function() { $('body').toggleClass('close'); }); $('.scroll').perfectScrollbar(); }); })(jQuery); </script>
書いてて全然意味わかんなくなってきましたが以上です。
COMMENTS
ベリー公 2019-10-25 20:36
ロゴがナビゲーションに含まれる・マウスオーバーでサブメニュー開閉タイプ
参照させていただきWEBページを作成中です。
初心者です。
sub-menu に表示するメニューの行間を狭めて上に少し詰めたいのですが
その寸法の変更はどこの数字をいらったらいいのでしょうか?
お手数ですが教えてください。
よろしくお願いします。
webOpixel 2019-10-26 09:57
サブメニューの間隔のことでしたら
「#global-nav .sub-menu-nav a」に「padding」を設定すればいけると思います!
ベリー公 2019-11-21 21:25
たびたびで申し訳ございませんがもう一つ教えてください。
ハンバーガーのメニューの線の太さをもう少し太くしたいのですが
線の太さはどこで調整いいのか教えてください。
よろしくお願いいたします。
webOpixel 2019-11-25 22:37
線だとborderですね。
スタイルはChromeのデベロッパーツールで調べるとすぐわかると思います。
webmaster 2019-12-21 06:58
サンプルコードを確かめました。メニュバーが気に入ったので加工しますが、利用しても良いでしょうか?©の記載があったので連絡させていただきました。
webOpixel 2019-12-22 15:58
コメントありがとうございます。
記事のコードは自由に使っていただいて大丈夫です。
TAKA 2019-12-28 11:21
探していたレスポンシブメニューだったのでとても参考になります!
マウスオーバーで横にサブメニューが開くタイプですが、こちらハンバーガーメニュー時にもサブメニュー開くことができるコードがあればご教授いただきたいです。
webOpixel 2019-12-31 10:05
コメントありがとうございます。
結構間があいてしまっているのでなんで開かないのかなという感じではありますが、機会がありましたらこちらも対応したいと思います。
2つ目のコードと参考にしていただけたら多分できるのかな。。。
a 2020-02-14 18:32
アコーディオンタイプのCSSいただきたいです。。
webOpixel 2020-03-02 11:12
コメントありがとうございます。
どうぞご自由にお使いください。
しらたま 2020-05-07 23:27
初心者です。
こういうメニューを探していたので、使わせていただきたいのですが、liのhomeやAboutをクリックしたら2階層目に遷移すると思うのですが、その際画面固定のようなことはできますでしょうか?
伝え方が難しいのですが…。
https://www.oralcare.co.jp/
上記ホームページのようにするのが理想なんです。
2階層目があるliのメニューから別のliにカーソルを当てても2階層目のが閉じようとしないと言えば伝わるでしょうか?
教えていただけると幸いです。
webOpixel 2020-05-09 14:40
「location.href」でURLを取得できるので、それとナビゲーションのリンクをマッチさせてクラスを付与するみたいな感じにすればいいと思います。
だいぶ昔の記事でもっとスマートなやり方はありますが下記記事を参考にしてみてください。
https://www.webopixel.net/javascript/200.html
お茶 2021-04-05 17:58
貴重なサイドバーとハンバーガーの組み合わせのメニューをありがとうございます!
ハンバーガーメニューの横もしくは下に”MENU”のテキストを入れるにはどうしたらよいでしょうか?
他サイトを参考に#nav-toggleにcontent:MENU;を追記するなどしてみたのですができませんでした。
お茶 2021-04-05 18:03
↑
一番目のデモの方のメニューです(ロゴがナビゲーションに含まれる・マウスオーバーでサブメニュー開閉タイプ)。
webOpixel 2021-04-06 22:11
例えばこんな感じとかでしょうか。(超適当ですが、、)
お茶 2021-04-09 16:47
MENUのテキスト表示できました!ありがとうございました!
ルーク 2022-01-21 10:09
素敵なサイドメニューの記事ありがとうございます。
ソースコードを利用させて頂いても宜しいでしょうか?
1点お聞きしたい事があります。
「ロゴはコンテンツ側・サブメニューがアコーディオンのタイプ」でbootstrap 4を一緒に利用するとサブメニューを閉じたときにレイアウトが崩れてしまいます。
なにかご存じでしたらご教示お願い致します。
webOpixel 2022-01-22 23:25
コードは自由に使用いただいて大丈夫です。
bootstrapでは試してませんが、クラス名がバッティングしているということではないでしょうか。