スマホサイトで便利なハンバーガーメニュー

今回は以下の要件を満たしたハンバーガーメニューのついたサイトベースを作成しました。
- スクロールしてもヘッダーがついてくる
- スクロール途中でもサイドメニューが開く
- サイドメニューを閉じたらスクロール途中の画面に戻る
一度作っておくとサイトを制作する時に便利ですし、構造を理解しておくとアレンジが必要になったときにも、すぐに対応できるようになりますので是非覚えておいてください😊
スクロールしてもついてくるハンバーガーメニューの概要
・デフォルト時ヘッダーのmenuをクリックして表示されるサイドメニューは非表示にする
・menuをクリックすると透過要素が上に敷かれてスクロールできなくなる
・透過要素の上にスライドメニューが表示される
・menuのクリック前後のスタイルはbodyにつくclass=”is-open”で切り替える
・ページ途中でスライドメニューが開いた時トップからのスクロール値を取得してその高さで止める
・スライドメニューを閉じたら止めていたスクロール値を消す
デモページはこちら
HTML
<header class="header">
<h1 class="header__logo">
<a href="#" class="header__logo-link">ロゴとか</a>
</h1>
<div class="nav__btn js-menu">
<a href="javascript:void(0)" class="nav__btn-link">menu</a>
</div>
</header>
<main class="main-contents">
<p style="margin-bottom: 500px;">コンテンツが入ります</p>
<p>スクロール途中</p>
</main>
<div class="nav">
<div class="nav__overlay js-menu"></div>
<div class="nav__content">
<div class="nav__btn js-menu">
<a href="javascript:void(0)" class="nav__btn-link">close</a>
</div>
<nav class="nav__inner">
<p>メニューが入る</p>
</nav>
</div>
</div>
<footer class="footer">
<p>footer要素が入ります</p>
</footer>
CSS
ヘッダーはdisplay:fixedで固定しています。
フレックスボックス(display:fixed)が幅広いブラウザに対応してから、サイトのレイアウトが一段と楽になりましたね。
今回はヘッダーのレイアウト時に便利なjustify-content: space-between;(要素を均等に配置し、初めと最後の要素を左右に寄せる)と、align-items: center;(縦中央配置)を使用しました。
どちらもとっても便利なので、ヘッダーのレイアウトにはかかせませんね!
body.is-openの時に、サイドメニューが表示されたときを表現しています。
body.is-open{
width: 100%;
height: 100%;
position: fixed;
}
.header{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: fixed;
top: 0;
padding: 5px 10px;
width: 100%;
height: 55px;
border-bottom: 1px solid #ccc;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
background: #fff;
overflow: hidden;
z-index: 10;
}
.header__logo{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
top: 0;
}
.header__logo-link{
color: #333;
font-size: 11px;
font-size: 1.1rem;
font-weight: normal;
text-decoration: none;
}
.header .nav__btn{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
top: 0;
position: static;
}
.header .nav__btn-link{
display: block;
color: #666;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-decoration: none;
cursor: pointer;
line-height: 1.15;
font-size: 11px;
font-size: 1.1rem;
}
.main-contents{
height: 1000px;
margin: 0 10px;
padding-top: 55px;
}
.footer{
padding: 20px 10px;
text-align: center;
background-color: #eee;
}
/* ハンバーガーメニュー内 */
.nav__overlay{
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 20;
background-color: rgba(0,0,0,0.6);
}
.nav__content{
position: fixed;
top: 0;
right: 0;
z-index: 30;
}
.nav__btn{
position: absolute;
top: 0;
left: -55px;
}
.nav__btn-link{
display: none;
}
/* 表示されたとき */
body.is-open .nav__btn-link{
display: block;
padding-top: 15px;
color: #fff;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
cursor: pointer;
text-decoration: none;
font-size: 11px;
font-size: 1.1rem;
}
body.is-open .nav__overlay,
body.is-open .nav__inner{
display: block;
}
.nav__inner{
display: none;
width: 250px;
padding: 10px;
overflow: auto;
background-color: #fff;
}
jQuery
はじめにスクロール値を取得し、代入できるようにしておきます。
ヘッダーのmenuをクリックしたときに、bodyのclassにis-openをつけます。
その際、スクロールしていた場所で止まるようにbodyにページトップからのスクロール値を直接スタイルで記述(style=”top: $px”)します。
同時に画面のブラウザの高さを取得し、オーバーレイ(透過要素)とサイドメニューに直接スタイルで記述(style=”height: $px;”)し、サイドメニューの要素が足りなくでも画面いっぱいまで表示されるように調整します。
/* スクロール値取得 */
var scrollTopValue = 0;
$(window).scroll(function() {
scrollTopValue = $(this).scrollTop();
});
$(function() {
/* サイドメニュー */
var saveScrollTopValue = 0;
$(".js-menu").on("click", function(){
$("body").toggleClass("is-open");
if ($("body").hasClass('is-open')) {
saveScrollTopValue = scrollTopValue;
$('body').css({"top":-scrollTopValue + 'px'});
} else {
$('body').css('top','');
$(window).scrollTop(saveScrollTopValue);
}
});
var windowH = window.innerHeight;
$('.nav__overlay, .nav__inner').css("height", windowH);
});
PCの場合は、スライドメニューを画面中央にレイアウトされるように調整する等してもよいですね!
レスポンシブにも対応できますので、是非お試しください😊
おすすめのjQuery参考書はこちら!