こんにちは、ナカムラです。
今回はスマホサイトではお馴染みのハンバーガーメニューの作り方をご紹介します。
タイトルに「階層の深い」と書きました。
ページ数の多いサイトでは、第2階層、第3階層とメニューが深くなっていきます。
階層が深くなるとメニューの数も増えていくため、メニューの中でも開閉するような仕様になっていきます。
そうすると、今度はメニューを閉じる時にも工夫が必要です。
下層メニューを開いた状態で閉じた時、何もしていないと次に開いた時に下層メニューが開いたままになります。
メニューが多い場合はそれが操作の妨げになることもあるため、下層メニューも一緒に閉じるようにすると良いです。
また、ブラウザバックで戻ったときや、同じページ内に遷移先がある場合は、クリックしたら閉じるという処理も必要になります。
今回はこれらに対応したハンバーガーメニューになります。
DEMO
See the Pen JavaScriptで階層の深いハンバーガーメニューを作る by Nakamura (@takayo-nakamura) on CodePen.
ハンバーガーメニューの開閉
const html = document.querySelector('html') const btn = document.getElementById('btn') const menu = document.getElementById('menu') // 下層のメニューを閉じる処理の関数 function subMenuClose () { const opens = document.querySelectorAll('.subNavBtn.is-active') // IE対策 const opensList = Array.prototype.slice.call(opens, 0) opensList.forEach(e => { e.classList.remove('is-active') }) } // ハンバーガーメニューの開閉 btn.addEventListener('click', () => { btn.classList.toggle('is-active') if (btn.classList.contains('is-active')) { // 開く処理 html.classList.add('is-menuOpen') } else { // 閉じる処理 html.classList.remove('is-menuOpen') subMenuClose() } })
btnというidに対してクリックイベントを付与し、is-activeというclassを付けたり外したりします。
また、btnにis-activeが付与されている時、HTMLにis-menuOpenを付与します。
classをJavaScriptで制御し、表示はスタイルシートで制御する方法になります。
CSSではis-menuOpen内の時に高さを持たせることで表示するようにしています。
#menu{ height: 0; overflow: hidden; .is-menuOpen &{ height: auto; } }
閉じる処理では開いた状態の下層メニューを探し、開くために付与しているclassを外すことで下層メニューを閉じます。
管理しやすいようにsubMenuClose()という関数に分けています。
下層メニューの開閉については次にご説明します。
下層のメニューの開閉
// 下層のメニューの開閉 const subNavs = document.querySelectorAll('.subNavBtn') // IE対策 const subNavsList = Array.prototype.slice.call(subNavs, 0) subNavsList.forEach(e => { e.addEventListener('click', () => { e.classList.toggle('is-active') }) })
先ほどと同じことをしていますが、下層メニューは複数入ることが多いため、対象をidではなくclassにしています。
subNavBtnというclassに対してクリックイベントを付与します。
ほぼ同じことをしているので細かい説明は省略いたします。
詳しくはDEMOのソースをご確認ください。
メニューをクリックしたら閉じる
// メニューをクリックしたら閉じる const links = document.querySelectorAll('.globalNav a') // IE対策 const linksList = Array.prototype.slice.call(links, 0) linksList.forEach(e => { e.addEventListener('click', function () { const btn = document.getElementById('btn') btn.click() // ハンバーガーメニューのボタンをクリックする }) })
こちらはメニューの中のリンクを押した時に付与するイベントです。
閉じる動作をもう一度書いたり、htmlタグへのclassの付与/削除もまとめて関数にしておいても良いですが、今回は「.click()」を使ってみました。
こちらはjQueryのtriggerメソッドと同じようにクリックした状態にすることができます。
なので、最初に書いたハンバーガーメニューのボタンを押した後の処理が走るため、下層メニューも含めて全て閉じることができます。
最後に
ナビゲーションはページの閲覧の邪魔にならないように、かつ必要な時には使いやすいように様々な工夫が必要になります。 今回はだいぶシンプルに書きましたがアニメーションを加えることでさらに操作方法がわかりやすくなります。 いろいろと工夫していきたいと思います。