ハンバーガーメニューを実装します。
【サンプルコード付き】
2023.07.25
はじめに
概要
Webサイトには欠かせないハンバーガーメニューを実装します。サンプルコードもありますので、コードを見ながら理解を深めていただければ幸いです。
※本記事の情報は執筆時点のものであり、閲覧時点では変更されている可能性があります。また、ご利用の環境によっては、本記事の内容が正常に動作しないことがあります。最新の情報については、公式サイトなどでご確認ください。
実装動画
Webサイトでよく見かけるハンバーガーメニューをクリックした際に、×になる動きを実装していきます。
サンプルコード
サンプルコードはこちらからダウンロードしてください。
HTML
<button class="mobile-menu__btn lg-none">
<!-- /.mobile-menu__btn -->
<button class="mobile-menu__btn lg-none">
<span></span>
<span></span>
<span></span>
</button>
<!-- /.mobile-menu__btn -->
<button class="mobile-menu__btn lg-none">
<span></span>
<span></span>
<span></span>
</button>
<!-- /.mobile-menu__btn -->
こちらがハンバーガーメニューを実装している箇所になります。予め準備していたlg-noneクラスを付与し、PC画面では削除しています。便利なクラスを記述したcommon.cssはこちらを参照してください。
Javascript
this.DOM.btn = document.querySelector(".mobile-menu__btn");
this.DOM.container = document.querySelector("#global-container");
this.DOM.container.classList.toggle("menu-open");
this.DOM.btn.addEventListener("click", this._toggle.bind(this));
export class Onclick {
constructor() {
this.DOM = {};
this.DOM.btn = document.querySelector(".mobile-menu__btn");
this.DOM.container = document.querySelector("#global-container");
this._addEvent();
}
// ハンバーガーメニュー #1/2
_toggle() {
this.DOM.container.classList.toggle("menu-open");
}
// ハンバークメニュー #2/2
_addEvent() {
this.DOM.btn.addEventListener("click", this._toggle.bind(this));
}
}
export class Onclick {
constructor() {
this.DOM = {};
this.DOM.btn = document.querySelector(".mobile-menu__btn");
this.DOM.container = document.querySelector("#global-container");
this._addEvent();
}
// ハンバーガーメニュー #1/2
_toggle() {
this.DOM.container.classList.toggle("menu-open");
}
// ハンバークメニュー #2/2
_addEvent() {
this.DOM.btn.addEventListener("click", this._toggle.bind(this));
}
}
考え方としては、ボタンをクリックした際に、サイトのトップクラスである親要素のglobalcontainerにクラスを付与します。付与するクラスはmenu-openとし、名前は任意です。こちらはtoggleメソッドとしてバインドされ、constructorで呼び出されます。
ポイント解説
すべてのコンテンツの親要素にクラスを付与する
この付与されたクラスを起点にCSSを調整すれば、様々なデザインを形成することができます。
// global-containerにmenu-openが付与されたときの挙動
background-color: $cMenuOpen;
transform: translateY(11px) rotate(135deg);
transform: translateX(-18px) scaleX(0);
transform: translateY(-11px) rotate(-135deg);
// global-containerにmenu-openが付与されたときの挙動
.menu-open {
& .mobile-menu {
&__btn {
span {
background-color: $cMenuOpen;
&:nth-child(1) {
transition-delay: 70ms;
transform: translateY(11px) rotate(135deg);
}
&:nth-child(2) {
transition-delay: 0s;
transform: translateX(-18px) scaleX(0);
}
&:nth-child(3) {
transition-delay: 140ms;
transform: translateY(-11px) rotate(-135deg);
}
}
}
}
}
// global-containerにmenu-openが付与されたときの挙動
.menu-open {
& .mobile-menu {
&__btn {
span {
background-color: $cMenuOpen;
&:nth-child(1) {
transition-delay: 70ms;
transform: translateY(11px) rotate(135deg);
}
&:nth-child(2) {
transition-delay: 0s;
transform: translateX(-18px) scaleX(0);
}
&:nth-child(3) {
transition-delay: 140ms;
transform: translateY(-11px) rotate(-135deg);
}
}
}
}
}
スクロール停止
ハンバーガーメニューが開いている場合は、スクロールを停止した場合があります。
bodyタグにoverflow: hidden;を付与することでスクロールを停止することができます。
それもJavascriptで対応が可能です。
Javascript
const body = document.body;
this.DOM.container.classList.toggle("menu-open");
if (this.DOM.container.classList.contains("menu-open")) {
// menu-open クラスがあるときにスクロールを無効化
body.style.overflow = "hidden";
// menu-open クラスがないときにスクロールを有効化
body.style.overflow = "auto";
_toggle() {
const body = document.body;
this.DOM.container.classList.toggle("menu-open");
if (this.DOM.container.classList.contains("menu-open")) {
// menu-open クラスがあるときにスクロールを無効化
body.style.overflow = "hidden";
} else {
// menu-open クラスがないときにスクロールを有効化
body.style.overflow = "auto";
}
}
_toggle() {
const body = document.body;
this.DOM.container.classList.toggle("menu-open");
if (this.DOM.container.classList.contains("menu-open")) {
// menu-open クラスがあるときにスクロールを無効化
body.style.overflow = "hidden";
} else {
// menu-open クラスがないときにスクロールを有効化
body.style.overflow = "auto";
}
}
document.bodyをbodyという変数に代入しています。
this.DOM.containerにmenu-openというクラスを切り替え(追加または削除)しています。
もしthis.DOM.containerがmenu-openクラスを持っている場合(つまりメニューが開いている状態)、ページのスクロールを無効にします。これはbody.style.overflowを”hidden”に設定することで行われます。
もしthis.DOM.containerにmenu-openクラスがなければ(メニューが閉じている状態)、ページのスクロールを有効に戻します。これはbody.style.overflowを”auto”に設定することで行われます。
つまり、この関数はメニューが開いているときはページのスクロールを無効にし、メニューが閉じているときはスクロールを有効にするためのものです。
その他
その他ハンバーガーメニューを使う際には、いくつか注意が必要です。
-ページ内のリンクに移動した時、ユーザーが別のセクションに移動した後もメニューが開いたままにならないように、menu-open クラスを削除する必要があります。
-モバイルで画面の横幅が変わった時も同様に、menu-open クラスを削除してメニューが閉じた状態を保つことが大切です。これは、画面サイズを変更した際にメニューが意図せず閉じられるのを防ぐためです。
それらは以下のコードで解決できます。
const body = document.body;
const links = document.querySelectorAll("a");
// 選択したすべてのリンクに対して、以下の処理を行います。
links.forEach((link) => {
// リンクがクリックされたときのイベントリスナーを追加します。
link.addEventListener("click", () => {
// もし"global-container"要素が"menu-open"クラスを持っている場合
if (this.DOM.container.classList.contains("menu-open")) {
// "menu-open"クラスを"global-container"要素から削除します。
this.DOM.container.classList.remove("menu-open");
// body要素のoverflowスタイルを"auto"に設定し、スクロールを可能にします。
body.style.overflow = "auto";
// ウィンドウのリサイズイベントにリスナーを追加します。
window.addEventListener("resize", function () {
// "global-container"というIDを持つ要素を取得します。
const el = document.getElementById("global-container");
const body = document.getElementsByTagName("body")[0];
const width = window.innerWidth;
// ウィンドウの幅が767pxより大きく、かつ"global-container"要素が"menu-open"クラスを持っている場合
if (width > 767 && el.classList.contains("menu-open")) {
// "menu-open"クラスを"global-container"要素から削除します。
el.classList.remove("menu-open");
// body要素のoverflowスタイルを"auto"に設定し、スクロールを可能にします。
body.style.overflow = "auto";
_addLinkEvent() {
// ページのbody要素を取得します。
const body = document.body;
// ページ内のすべてのaタグを選択します。
const links = document.querySelectorAll("a");
// 選択したすべてのリンクに対して、以下の処理を行います。
links.forEach((link) => {
// リンクがクリックされたときのイベントリスナーを追加します。
link.addEventListener("click", () => {
// もし"global-container"要素が"menu-open"クラスを持っている場合
if (this.DOM.container.classList.contains("menu-open")) {
// "menu-open"クラスを"global-container"要素から削除します。
this.DOM.container.classList.remove("menu-open");
// body要素のoverflowスタイルを"auto"に設定し、スクロールを可能にします。
body.style.overflow = "auto";
}
});
});
}
_removeMenuOpenClass() {
// ウィンドウのリサイズイベントにリスナーを追加します。
window.addEventListener("resize", function () {
// "global-container"というIDを持つ要素を取得します。
const el = document.getElementById("global-container");
// ページのbody要素を取得します。
const body = document.getElementsByTagName("body")[0];
// ウィンドウの内部幅を取得します。
const width = window.innerWidth;
// ウィンドウの幅が767pxより大きく、かつ"global-container"要素が"menu-open"クラスを持っている場合
if (width > 767 && el.classList.contains("menu-open")) {
// "menu-open"クラスを"global-container"要素から削除します。
el.classList.remove("menu-open");
// body要素のoverflowスタイルを"auto"に設定し、スクロールを可能にします。
body.style.overflow = "auto";
}
});
}
_addLinkEvent() {
// ページのbody要素を取得します。
const body = document.body;
// ページ内のすべてのaタグを選択します。
const links = document.querySelectorAll("a");
// 選択したすべてのリンクに対して、以下の処理を行います。
links.forEach((link) => {
// リンクがクリックされたときのイベントリスナーを追加します。
link.addEventListener("click", () => {
// もし"global-container"要素が"menu-open"クラスを持っている場合
if (this.DOM.container.classList.contains("menu-open")) {
// "menu-open"クラスを"global-container"要素から削除します。
this.DOM.container.classList.remove("menu-open");
// body要素のoverflowスタイルを"auto"に設定し、スクロールを可能にします。
body.style.overflow = "auto";
}
});
});
}
_removeMenuOpenClass() {
// ウィンドウのリサイズイベントにリスナーを追加します。
window.addEventListener("resize", function () {
// "global-container"というIDを持つ要素を取得します。
const el = document.getElementById("global-container");
// ページのbody要素を取得します。
const body = document.getElementsByTagName("body")[0];
// ウィンドウの内部幅を取得します。
const width = window.innerWidth;
// ウィンドウの幅が767pxより大きく、かつ"global-container"要素が"menu-open"クラスを持っている場合
if (width > 767 && el.classList.contains("menu-open")) {
// "menu-open"クラスを"global-container"要素から削除します。
el.classList.remove("menu-open");
// body要素のoverflowスタイルを"auto"に設定し、スクロールを可能にします。
body.style.overflow = "auto";
}
});
}
まとめ
- ウェブサイトでハンバーガーメニューの実装は必須である
- トップの親要素にクラスを付与することで、デザインが形成しやすくなる
- クラスの付与にはJavascriptを使用
- toggleメソットを活用