少し前に「jQueryでレスポンシブメニューをアコーディオンタイプでシンプルに実装する方法」と題して、スマートフォン向けレイアウト時ではメニューをアコーディオン動作で展開するレスポンシブナビゲーションUIを紹介しました。

レスポンシブナビゲーションUIのパターンとしてはアコーディオン動作ではなく
ハンバーガーメニューボタンを使って、画面のサイドからメニューボタンを
スライドさせて表示させるタイプもあります。

今回はその画面横からスライドさせて
メニューボタンを展開するタイプのレスポンシブメニューUIを
jQueryを使ってできるだけシンプルな構成で作ってみたのでご紹介してみます。

jQueryでレスポンシブメニューを横スライドタイプでシンプルに実装する方法

「jQueryでレスポンシブメニューを横スライドタイプでシンプルに実装する方法」サンプルを別枠で表示

サンプルでは前回同様に
ウィンドウサイズが768px以上ならばPC向けナビゲーション、
768px以下だったらスマートフォン向けのナビゲーションに切り替わります。

PC向けナビゲーションではボタン類は画面内に横並びですべて表示されます。
スマートフォン向けナビゲーションではページ上部に
ハンバーガーメニューボタンを配置しクリックすることで
画面横からスライド動作によってボタン類が出現します。

全体構成についてまずはHTMLから。

◆HTML
<nav id="menuList">
<ul>
<li><a href="#">[1] MENU</a></li>
<li><a href="#">[2] MENU</a></li>
<li><a href="#">[3] MENU</a></li>
<li><a href="#">[4] MENU</a></li>
<li><a href="#">[5] MENU</a></li>
</ul>
</nav><!-- /#menuList -->

HTMLではナビゲーションで使用するリンクボタンをリストで構成し、
リスト全体を任意のIDもしくはクラスで囲います。

PC向けレイアウトでもスマートフォン向けでも
この一つのHTMLソースを使用します。

この要素に対してCSSは以下のように指定します。

◆CSS
/* ------------------------------
   #menuList
------------------------------ */
#menuList {
	width: 100%;
	height: 45px;
	border-top: #aaa 1px solid;
	border-bottom: #aaa 1px solid;
	position: relative;
	z-index: 10;
	background: #ebebeb;
}

#menuList ul {
	margin: 0 auto;
	width: 800px;
	height: 45px;
	text-align: left;
}

#menuList ul li {
	width: 160px;
	height: 45px;
	float: left;
	border-left: #aaa 1px solid;
	box-sizing: border-box;
}

#menuList ul li:last-child {
	border-right: #aaa 1px solid;
}

#menuList ul li a {
	height: 45px;
	font-weight: bold;
	line-height: 45px;
	display: block;
	text-align: center;
	transition: all 0.2s linear;
}

#menuList ul li:hover > a {
	background: #fff;
}

#contents {
	margin: 0 auto;
	padding: 40px 0;
	width: 800px;
	text-align: left;
}

#contents p {
	padding-bottom: 2em;
	font-size: 1em;
	line-height: 2em;
}

/* ------------------------------
   MEDIAQUERIES LAYOUT
------------------------------ */
@media only screen and (max-width: 800px) {
	#menuList ul {
		width: 100%;
	}

	#menuList ul li {
		width: 20%;
	}
}

/* ------------------------------
   MEDIAQUERIES[SP]LAYOUT
------------------------------ */
@media only screen and (max-width: 768px) {
	#menuList {
		display: none;
	}

	#menuOverlay {
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		background-color: rgba(0,0,0,0.6);
		display: none;
		position: fixed;
		z-index: 9997;
	}

	#switchBtnArea {
		width: 100%;
		height: 60px;
		background: #3c3c3c;
		border-bottom: #aaa 1px solid;
		position: relative;
	}

	#switchBtnArea #switchBtn {
		top: 10px;
		left: 10px;
		width: 40px;
		height: 40px;
		display: block;
		background: #a7a7a7;
		position: absolute;
		border-radius: 5px;
		z-index: 9998;
	}

	#switchBtnArea #switchBtn span {
		left: 20%;
		width: 60%;
		height: 4px;
		display: block;
		position: absolute;
		background-color: #fff;
		border-radius: 5px;
		transition: all 0.2s linear;
	}
	#switchBtnArea #switchBtn span:nth-of-type(1) {
		top: 10px;
		-webkit-transform: rotate(0);
		transform: rotate(0);
	}
	#switchBtnArea #switchBtn span:nth-of-type(2) {
		top: 18px;
		-webkit-transform: scale(1);
		transform: scale(1);
	}
	#switchBtnArea #switchBtn span:nth-of-type(3) {
		bottom: 10px;
		-webkit-transform: rotate(0);
		transform: rotate(0);
	}

	#switchBtnArea #switchBtn.btnClose {
		background: transparent;
	}
	#switchBtnArea #switchBtn.btnClose span:nth-of-type(1) {
		top: 18px;
		-webkit-transform: rotate(-45deg);
		transform: rotate(-45deg);
	}
	#switchBtnArea #switchBtn.btnClose span:nth-of-type(2) {
		-webkit-transform: scale(0);
		transform: scale(0);
	}
	#switchBtnArea #switchBtn.btnClose span:nth-of-type(3) {
		bottom: 18px;
		-webkit-transform: rotate(45deg);
		transform: rotate(45deg);
	}

	#rwdMenuWrap {
		top: 0;
		left: -200px;
		width: 200px;
		height: 100%;
		background: #3c3c3c;
		overflow: auto;
		position: fixed;
		z-index: 9999;
	}

	#rwdMenuWrap ul {
		width: 100%;
	}

	#rwdMenuWrap ul li {
		width: 100%;
		border-bottom: #aaa 1px solid;
	}

	#rwdMenuWrap ul li a {
		padding: 15px 20px;
		text-align: left;
		display: block;
		background: #ebebeb;
		position: relative;
	}

	#rwdMenuWrap ul li a:after {
		content: '';
		margin-top: -4px;
		top: 50%;
		right: 15px;
		width: 8px;
		height: 8px;
		color: #888;
		font-size: 1em;
		font-weight: bold;
		line-height: 1.2em;
		display: block;
		position: absolute;
		border-top: 2px solid #b0b0b0;
		border-right: 2px solid #b0b0b0;
		-webkit-transform: rotate(45deg);
		transform: rotate(45deg);
	}

	#contents {
		width: 100%;
	}

	#contents p {
		padding: 0 20px 2em 20px;
	}
}

/* ------------------------------
   CLEARFIX ELEMENTS
------------------------------ */
#menuList > ul:before,
#menuList > ul:after {
	content: " ";
	display: table;
}
#menuList > ul:after {clear: both;}
#menuList > ul {*zoom: 1;}

768px以上のPC向けレイアウトでは
ボタンを横並びにするプロパティを指定します。

768px以下のスマートフォン向けレイアウトでは
PC向けレイアウト時に使用している要素は「display:none;」で非表示にします。

スクリプト側でメニューボタンのソースを
「#switchBtnArea」にコピーして制御します。

リスト要素を囲う「#rwdMenuWrap」を「posiiotn:fixed」にして位置固定し
「left」の値を要素幅と同じ値分「-(マイナス)」で指定し
画面の外へ隠しておきます。

ハンバーガーメニューボタンの装飾・アニメーションと
コンテンツエリアとナビゲーションメニューエリアの間に挟まることになる
オーバーレイ要素「#menuOverlay」に対しても背景色等を指定します。

そして実際の切り替えスクリプトは以下の様になります。

◆SCRIPT
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(function(){
	var rwdMenu = $('#menuList'),
	switchPoint = 768,
	slideSpeed = 300,
	fadeSpeed = 500;

	var menuSouce = rwdMenu.html();

	$(window).load(function(){

		function menuSet(){
			if(window.innerWidth <= switchPoint){
				if(!($('#rwdMenuWrap').length)){
					$('body').prepend('<div id="menuOverlay"></div><div id="switchBtnArea"><a href="javascript:void(0);" id="switchBtn"><span></span><span></span><span></span></a></div><div id="rwdMenuWrap"></div>');
					$('#rwdMenuWrap').append(menuSouce);

					var menuOverlay = $('#menuOverlay'),
					switchBtn = $('#switchBtn'),
					btnLeft = parseInt(switchBtn.css('left')),
					menuWrap = $('#rwdMenuWrap'),
					menuWidth = menuWrap.outerWidth();

					switchBtn.on('click', function(){
						if($(this).hasClass('btnClose')){
							$(this).removeClass('btnClose').removeAttr('style');
							menuOverlay.stop().animate({opacity:'0'},fadeSpeed,function(){
								menuOverlay.removeAttr('style');
							});
							menuWrap.stop().animate({left:'-' + menuWidth + 'px'},slideSpeed);
							$('body').removeAttr('style');
						} else {
							$(this).addClass('btnClose').css({position:'fixed'}).stop().animate({left:menuWidth + btnLeft},slideSpeed);
							menuOverlay.css({display:'block',opacity:'0'}).stop().animate({opacity:'1'},fadeSpeed);
							menuWrap.stop().animate({left:'0'},slideSpeed);
							$('body').css({position:'fixed'});
						}
					});
				}
			} else {
				$('#menuOverlay,#switchBtnArea,#rwdMenuWrap').remove();
				$('body').removeAttr('style');
			}
		}

		$(window).on('resize', function(){
			menuSet();
		});

		menuSet();
	});
});
</script>

スクリプト開始部分にある設定値の内容は以下の様になっています。

rwdMenu = $(‘#menuList’) 切り替えUI全体を囲う要素(CSSクラスでも可)
switchPoint = 768 PC向けとスマートフォン向けで切り替えるサイズ
slideSpeed = 300 メニュー開閉時のスライドアニメーション時間
fadeSpeed = 500 オーバーレイ要素が出現する際のフェードアニメーション時間

これらの設定値を変更することで微調整が可能になっています。
「switchPoint」で設定する値は、CSSで設定したメディアクエリと同じ値にします。

ページロード時およびウィンドウリサイズ時に
ウィンドウサイズを取得します。

「switchPoint」で設定された値(サンプルでは768px)よりも大きい
PC向けレイアウトの場合はスクリプト側では特になにもしません。

「switchPoint」で設定された値よりも小さければ
スマートフォン向けメニューとしてのソースをオーバーレイ要素と合わせて生成し
ハンバーガーメニューのボタンクリック時の開閉動作を指定します。

スマートフォン向けメニューソースは
「switchPoint」で設定された値よりも大きい場合は
要素自体を削除します。(生成させません)

以上がスライドタイプのレスポンシブ対応メニューUIを
jQueryでシンプルに実装する紹介でした。

レスポンシブWebサイトでナビゲーションメニューを
コンパクトに扱う場合になどに活用できるUIかと思っています。

PC向けとスマートフォン向けでナビゲーションメニューUIを
スライドタイプで切り替える際にぜひ。。。

サンプルファイルをダウンロードしたい方はこちらから

  • このエントリーをはてなブックマークに追加
BlackFlag
FOLLOW

Related Posts

Comments (6)

  • tone | 2016.07.29 10:33

    こんにちは。

    少し前に、

    jQueryでレスポンシブメニューをアコーディオンタイプでシンプルに実装する方法
    http://black-flag.net/jquery/20160119-5897.html

    にコメントさせていただきました者ですが、

    こちらの仕様でも、メニューを上部に固定する方法を教えていただければ幸いです。

    お手数ですが、よろしくお願い致します!

  • BlackFlag | 2016.07.31 1:20

    >toneさん
    コメントありがとうございます。

    もう一つの方で返答させていただいた内容とほぼ同じになりますが
    メニューの上部固定はスクリプトから指定するのではなく
    CSSのみで対応させることが可能かと思いますので
    メニューボタン要素となる「#switchBtnArea」に対して
    「position:fixed」と「z-index」のプロパティを追加するなどして
    調整いただければと思います

    お試しください。
    よろしくお願いします。

  • milly | 2016.08.14 1:23

    初めまして!

    こちらのハンバーガーメニュー(switchBtnArea)についてですが、

    ”menuList”とは別の内容(他のコンテンツリンクへ飛ばしたい)を入れたいのですが、

    どのようにすればよろしいでしょうか?

    お手数ですが宜しくお願い致します。

  • BlackFlag | 2016.08.14 13:30

    >millyさん
    コメントありがとうございます。

    当記事のスクリプトはPC用とスマホ用で
    同じメニューソースの形状を変える、という構成になっておりますので、
    ご質問いただきましたような、PC用とスマホ用でそれぞれ違う構成のメニュー切り替えを考えると
    当記事のスクリプトを使用せずに、
    HTMLにPC用とスマホ用のメニューソースをそれぞれ記載して
    CSSメディアクエリーで表示/非表示を切り替える方が
    適切なのではないかと思っております。

    お試しください。
    よろしくお願いします。

  • 浅井 | 2017.06.19 21:12

    はじめまして

    こちらのスクリプトは階層形式のメニューには対応されていますか?
    もしされていないのであれば対応方法を教えていただけると助かります。

    よろしくお願いします。

  • BlackFlag | 2017.06.25 9:51

    >浅井さん
    コメントありがとうございます。

    当記事のスクリプト構成では、
    階層形式のメニューでの実装は想定しておりません。

    ですが、このスクリプトを応用して
    そのようなレスポンシブメニューを作成することは可能だと思いますので
    またサンプル等を用意することができましたら
    ここで紹介させていただきたいと思います。

    よろしくお願いします。







コメント内容

※コメントにHTMLタグを直接入力しないでください。
※HTMLタグを入力する際はタグ一つ一つの括弧「<」「>」を全角に変換して入力してください。
コメントは承認制になっているのですぐには反映されません。コメント頂いた内容については出来る限り早めの対応を心掛けていますが、時期によって返答が遅くなってしまうことがありますので、何卒ご了承ください。
» コメントについてのご注意  |  » ライセンスに関して

jQueryでレスポンシブメニューを横スライドタイプでシンプルに実装する方法

Hatena Bookmark
Popular Entries
Recent Entries
PR
Facebook
Tweets
Animal Protection
  • 福島被曝牛支援のお願い
  • NO FUR
Books
  • jQuery Technical Note
  • 外掛OUT! jQuery 高手精技
Partner