少し前に「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」で設定された値よりも大きい場合は
要素自体を削除します。(生成させません)
こちらでも紹介させていただいています。
・書籍「プラグインを使わないスキルを身につけたい人のためのjQueryテクニカルノート」出版について
https://black-flag.net/jquery/20160202-5926.html
以上がスライドタイプのレスポンシブ対応メニューUIを
jQueryでシンプルに実装する紹介でした。
レスポンシブWebサイトでナビゲーションメニューを
コンパクトに扱う場合になどに活用できるUIかと思っています。
PC向けとスマートフォン向けでナビゲーションメニューUIを
スライドタイプで切り替える際にぜひ。。。