WEBOPIXEL

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

Posted: 2017.09.21 / Category: HTML&CSS, javascript / Tag: 

近年ではモニターサイズが広くなってきた影響もあり、サイドバーを固定表示させてるサイトが多くみられるようになった気がします。
そこでここでは画面が狭くなるとハンバーガメニューになるレスポンシブに対応した固定サイドバーの作成方法をご紹介します。

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 

例えばこんな感じとかでしょうか。(超適当ですが、、)

<div id="nav-toggle">
	<div>
		<span></span>
		<span></span>
		<span></span>
	</div>
<i style="
    top: 30px;
    position: relative;
    font-size: 10px;
">MENU</i>
</div>

お茶 2021-04-09 16:47 

MENUのテキスト表示できました!ありがとうございました!

ルーク 2022-01-21 10:09 

素敵なサイドメニューの記事ありがとうございます。
ソースコードを利用させて頂いても宜しいでしょうか?

1点お聞きしたい事があります。
「ロゴはコンテンツ側・サブメニューがアコーディオンのタイプ」でbootstrap 4を一緒に利用するとサブメニューを閉じたときにレイアウトが崩れてしまいます。
なにかご存じでしたらご教示お願い致します。

webOpixel 2022-01-22 23:25 

コードは自由に使用いただいて大丈夫です。
bootstrapでは試してませんが、クラス名がバッティングしているということではないでしょうか。

ベリー公 2023-10-20 14:35 

いつもお世話になります。
ハンバーガーメニューの3本線の一番下の線が切れて表示されなくなったのですが、どのコードの数字をいらったら修正できますか?
よろしくお願いします。

LEAVE A REPLY

コードを書く場合は<pre>で囲んでください。