ハンバーガーメニュー(micromodal.js使用)
※自分用の学習記録になります。
(Micromodal.jsによるハンバーガーメニューを実装した参考サイトが少なかったので)
経緯
今まで自作にてハンバーガーメニューを実装していましたがアクセシビティなど考慮することが意外と多いことに気付かされ自作よりもプラグイン(今回はMicromodal.js)を使用する方が良いと風の噂で聞きましたので学習も兼ねて実装していこうと。
Micromodal.js について
公式:https://micromodal.vercel.app/
・1.9kbの軽量ライブラリ
・WAI-ARIAガイドラインに準拠
・素のJavaScriptにて記述されている
・モーダルを開いている際、背景の固定の有無が簡単に設定できる。
etc...
今回のゴール
以下の点を考慮し
1. メニューが開いている時に背景を固定(スクロール無効)
2. メニューを閉じた際、画面上部への移動を防止
3. ページ内リンクへのスムーススクロール
インストール
・npmやyarnにてインストールする。
・もしくはCDNにてを読み込む。
npm / yarn
npm install micromodal --save
<!-- もしくは -->
yarn add micromodal --save
CDN
https://unpkg.com/micromodal/dist/micromodal.min.js
使い方
基本的な構造
<div id="modal-1" aria-hidden="true">
<div tabindex="-1" data-micromodal-close>
<div role="dialog" aria-modal="true" aria-labelledby="modal-1-title" >
<header>
<h2 id="modal-1-title">
Modal Title
</h2>
<button aria-label="Close modal" data-micromodal-close></button>
</header>
<div id="modal-1-content">
Modal Content
</div>
</div>
</div>
</div>
モーダルの開閉
buttonなどで属性を以下のように制御
”data-micromodal-trigger ”にてモーダルを開く。
"data-micromodal-close"にてモーダルを閉じる。
<!-- 開ける -->
<button type="button" data-micromodal-trigger="modal-1">OPEN</button>
<!-- 閉じる -->
<button aria-label="Close modal" data-micromodal-close></button>
またはJavaScriptからも操作することができます。
※今回はコチラを利用して開閉を制御していきます。
<!-- 開ける -->
MicroModal.show('modal-id');
<!-- 閉じる -->
MicroModal.close('modal-id');
JavaScript
<!-- 実行 -->
MicroModal.init();
オプション
オプションにて簡単にページのスクロール無効やモーダルの開閉の為のクラス名の指定などが行えますので以下を参照
・onShow (function)
モーダルが開く時に実行される関数。
1つ目のパラメータ:モーダルオブジェクト
2つ目のパラメータ:トリガー要素
・onClose (function)
モーダルが閉じた時に実行される関数。
パラメータの指定は"onShow"と同様。
・openTrgger (string)
モーダルを開くためのカスタムデータ属性を指定が可能。
デフォルト:data-micromodal-trigger
・closeTrigger (string)
モーダルを閉じるためのカスタムデータ属性を指定が可能。
デフォルト:data-micromodal-close
・openClass (string)
モーダルを閉じるためのカスタムデータ属性を指定が可能。
デフォルト: data-micromodal-closeです
・disableScroll (boolean)
モーダルが開いている間、ページのスクロールが無効。
デフォルト:false
・disableFocus (boolean)
最初のフォーカス可能な要素のオートフォーカスを無効。
デフォルト:false
・awaitOpenAnimation (boolean)
cssアニメーションを使用してモーダルを開く場合は、trueに設定。
モーダル内の要素に焦点を合わせる前に、アニメーションが終了するのを待つことが可能。
デフォルト:false
・awaitCloseAnimation (boolean)
cssアニメーションを使用してモーダルを非表示にする場合は、trueに設定。アニメーションが終了するのを待ってDOMから削除。
デフォルト:false
・debugMode
コンソールに表示される警告を抑制。
デフォルト:false
<!-- 例 -->
MicroModal.init({
openClass: 'is-open',
disableScroll: true,
});
<!-- JavaScriptで操作する場合 -->
MicroModal.show('modal-1', {
disableScroll: true
});
サンプルのソースコードも下記より行けるので確認してみると良いかもしれません(今回の実装に関しても土台の参考にさせて頂きました。)
https://gist.github.com/ghosh/4f94cf497d7090359a5c9f81caf60699#file-micromodal-html
実装
全体像は上部のcodepenを参照して頂いてココではポイントになりそうな部分を記述していきます。
まずは今回実装するにあたっての要点の整理していきます。
・ボタンはopen/closeを別々ではなく一つにて処理できるように
・メニューの開閉はdata属性ではなくJavaScript側の操作に行って行きます。(開閉のトリガーは属性にて行う下記参照)
HTML
buttonの"aria-expanded"属性をトリガーとし
それに伴って"MicroModal.show() / MicroModal.close()"を使用しメニューの開閉を制御していきます。
<!-- header -->
<header>
<button class="c-hamburger c-button" type="button" id="js-buttonHamburger" aria-expanded="false">
<span class="c-hamburger__line"></span>
</button>
</header>
上記buttonにてメニューを開く時にaria-hidden="true"から"false"にすることでメニューを開くようにしていきます。
また、今回はページ内リンクも付与するので各メニューのリンクも記述します。
<!-- コンテンツ -->
<!-- aria-hiddenにて開閉の制御 -->
<div class="modal_container" id="modal-1" aria-hidden="true">
<div tabindex="-1" data-micromodal-close>
<div role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
<div id="modal-1-content">
<ul class="menu_list">
<li class="menu_item"><a class="menu_link" href="#anchor_01">ホーム</a></li>
<li class="menu_item"><a class="menu_link" href="#anchor_02">ABOUT</a></li>
<li class="menu_item"><a class="menu_link" href="#anchor_03">ACCESS</a></li>
<li class="menu_item"><a class="menu_link" href="#anchor_04">CONTACT</a></li>
</ul>
</div>
</div>
</div>
</div>
ちなみにメニューを開くと"is-open"というクラス名が付与されるのでコチラでcssにてスタイルしていくことも可能です。
CSS(SCSS)
[aria-hidden='false']が付与つまりメニューが開いた時のスタイルを記述していきます。
(スタイルに関しては好みで!)
.modal_container {
width: 80%;
height: 80%;
display: none;
padding: 60px 20px;
background-color: rgb(204, 255, 204);
}
<!-- メニューが開いた時のスタイルを記述 -->
.modal_container[aria-hidden='false'] {
position: fixed;
top: 0;
left: 0;
display: block;
z-index: 20;
overflow-y: scroll;
}
JavaScript
ページ内リンクへのスムーススクロール
const anchorLinks = document.querySelectorAll('a[href^="#"]');
const anchorLinksArr = Array.prototype.slice.call(anchorLinks);
const btn = document.querySelector('#js-buttonHamburger');
anchorLinksArr.forEach((link) => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetId = link.hash;
const targetElement = document.querySelector(targetId);
const targetoffsetTop = window.pageYOffset + targetElement.getBoundingClientRect().top;
if (btn.ariaExpanded == 'true') {
btn.ariaExpanded = false;
}
// リンク先に移るに合わせてメニューを閉じる処理
anchorLinksArr.ariaExpanded = false;
MicroModal.close('modal-1');
window.scrollTo({
top: targetoffsetTop - 60,
behavior: 'smooth',
});
});
});
メニューの開閉
btn.addEventListener('click', function () {
const bodyElement = document.querySelector('body');
<!-- メニュー開ける処理 -->
if (btn.ariaExpanded == 'false') {
btn.ariaExpanded = true;
MicroModal.show('modal-1', {
disableScroll: true, // ページスクロールを無効に
awaitOpenAnimation: true, // 開閉時のアニメーションを可能に
});
<!-- メニュー閉じる処理 -->
} else {
btn.ariaExpanded = false;
MicroModal.close('modal-1', {
awaitCloseAnimation: true,
});
}
});
以上にて完成がコチラ(上部と同)。
ひとまず目標としていたものは出来たかと!
まだまだ学習中でコードも助長的ではありますがせっかく学んで実装したのでこうして整理しておきたいと思い記述。
また、もっと"こうした方が良いよ!"とかあれば是非教えて頂ければ幸いです。
参考にさせて頂いたサイト
・アクセシビティに関して
https://zenn.dev/tak_dcxi/articles/f958e96888ee47
・micromodal.jsに関して
https://www.willstyle.co.jp/blog/3646/
https://www.hypertextcandy.com/micromodal-js
https://www.evoworx.co.jp/blog/accessibility-modal/
・スムーススクロールに関して
https://web-dev.tech/front-end/javascript/anchor-link-smooth-scroll/
・メニューを閉じた際、画面上部への移動を防止
https://codepen.io/junpei-sugiyama/pen/pojXPNE?editors=0010
(コチラではjQueryにての実装になっております)
・ハンバーガーメニューの実装
https://shibajuku.net/make-hamburger-button/
この記事が気に入ったらサポートをしてみませんか?