Web制作 JavaScript

Micromodal.jsを使ったハンバーガーメニューの作り方(背景固定・オーバーレイあり)

2024年2月27日

※ 当サイトではアフィリエイト広告を利用しています

ハンバーガーメニューってどうやって作るの?

コーディング案件で非常に多い実装、ハンバーガーメニュー。

LPでは無いことも多いですが、コーポレートサイトなど複数ページの場合は、ほぼ確実にあります。

そして頻出する実装でありながら、細かいことを気にするとかなり難しいです。

そこで今回は、Micromodal.jsというJavaScriptのライブラリを使った、ハンバーガーメニューの作り方を解説していきます。

Micromodal.jsの使い方とMicromodal.jsを使ったモーダルウィンドウの作り方は、以下の記事を参照下さい。

簡単にモーダルウィンドウを実装できるライブラリ Micromodal.jsの使い方
Micromodal.jsの使い方【モーダルウィンドウを簡単に実装できるライブラリ】

続きを見る

じゅんぺいブログは、Web制作コーディングWordPress制作)の技術記事を中心に、約500記事公開しています。ぜひ他の記事も参考にしてみてください!
完全無料のプログラミングスクール『ZeroPlus Gate』
30日間でWeb制作を学べる無料のプログラミングスクールがこちら
いきなり数十万するプログラミングスクールは厳しい・・・という人のお試しに最適です。
現在は無料ですがいつ有料になるか分からないので、気になる方はお早めに👇
(有料になっていたらすいません🙇‍♂️)

\ 完全無料 /

ZeroPlus Gate公式サイト

毎日先着制!

micromodal.jsを使ったハンバーガーメニューの作り方

ハンバーガーメニューの作り方は多種多様ですが、今回はシンプルな以下の6種類ご紹介します。

  • 右からスライド(画面半分)
  • 右からスライド(全画面)
  • 上からスライド(画面半分)
  • 上からスライド(全画面)
  • 全画面フェード
  • ハンバーガーメニュー内でスクロール

共通の機能は以下になります。

  • 開くときに背景を暗くする(オーバーレイ)
  • 背景(オーバーレイ)をクリックで閉じる
  • 開くときに背景を固定する(スクロール不可)
  • 閉じるときにページトップに移動しない
  • リンクをクリックするとメニューを閉じながらスムーススクロール
  • ESCボタンで閉じる

全画面ではオーバーレイはなくてもいいかも知れませんが、ゆっくりメニューを開閉するので、開き切るまで薄暗くなるように今回はそのまま設定しています。

 

共通のコード

まずは、基本となる共通のコードを見ていきます。

 

HTML

基本となるHTMLはこちらです。

<header>
  <!-- ハンバーガーメニューボタン -->
  <button
    class="hamburger"
    type="button"
    id="js-buttonHamburger"
    aria-expanded="false"
  >
    <span class="hamburger-line">
      <span class="visuallyHidden">メニューを開閉する</span>
    </span>
  </button>
</header>
<!-- オーバーレイ -->
<div class="overlay" id="js-overlay"></div>
<!-- ハンバーガーメニュー -->
<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="#anchor01">HOME</a>
          </li>
          <li class="menu-item">
            <a class="menu-link" href="#anchor02">ABOUT</a>
          </li>
          <li class="menu-item">
            <a class="menu-link" href="#anchor03">SHOP</a>
          </li>
          <li class="menu-item">
            <a class="menu-link" href="#anchor04">NEWS</a>
          </li>
          <li class="menu-item">
            <a class="menu-link" href="#anchor05">ACCESS</a>
          </li>
          <li class="menu-item">
            <a class="menu-link" href="#anchor06">CONTACT</a>
          </li>
        </ul>
      </div>
    </div>
  </div>
</div>
<!-- メインコンテンツ -->
<main>
  <section class="section01" id="anchor01">
    <h2 class="section-title">HOME</h2>
  </section>
  <section class="section02" id="anchor02">
    <h2 class="section-title">ABOUT</h2>
  </section>
  <section class="section03" id="anchor03">
    <h2 class="section-title">SHOP</h2>
  </section>
  <section class="section04" id="anchor04">
    <h2 class="section-title">NEWS</h2>
  </section>
  <section class="section05" id="anchor05">
    <h2 class="section-title">ACCESS</h2>
  </section>
  <section class="section06" id="anchor06">
    <h2 class="section-title">CONTACT</h2>
  </section>
</main>

オーバーレイに関しては、不要であれば削除して下さい。

 

CSS

共通のCSSはこちらです。

/* アクセシビリティ対策 */
.visuallyHidden {
  border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
/* ハンバーガーボタンのスタイル */
.hamburger {
  appearance: none;
  background-color: transparent;
  border: none;
  cursor: pointer;
  display: block;
  height: 32px;
  outline: none;
  position: fixed;
  right: 30px;
  top: 30px;
  transition: transform .6s, width .6s;
  width: 40px;
  z-index: 200; /* メニューよりも上にする */
}
/* ハンバーガーメニュー三本線 */
.hamburger-line {
  background-color: #000;
  height: 2px;
  left: 0;
  margin: auto;
  position: absolute;
  right: 0;
  top: 0;
  transition: inherit;
  width: 100%;
}
.hamburger-line::before,
.hamburger-line::after {
  background-color: #000;
  content: "";
  display: block;
  height: 100%;
  position: absolute;
  transition: inherit;
  width: 100%;
}
.hamburger-line::before {
  top: 10px;
}
.hamburger-line::after {
  top: 20px;
}
/* ハンバーガーメニュー三本線オープン時 */
.hamburger[aria-expanded="true"] .hamburger-line {
  transform: translateY(15px) rotate(-45deg);
}
.hamburger[aria-expanded="true"] .hamburger-line::before {
  transform: translateY(-12px) translateX(20px) rotate(45deg);
  width: 0;
}
.hamburger[aria-expanded="true"] .hamburger-line::after {
  transform: translateY(-20px) rotate(90deg);
}
/* オーバーレイのスタイル */
.overlay {
  background-color: #333;
  cursor: pointer;
  height: 100vh;
  left: 0;
  opacity: 0;
  position: fixed;
  top: 0;
  transition: opacity .6s, visibility .6s;
  visibility: hidden;
  width: 100vw;
  z-index: 10; /* メニューよりも下にする */
}
.overlay.active {
  opacity: .8;
  visibility: visible;
}
/* メニューのスタイル */
.modal-container {
  background-color: #fff;
  position: fixed;
  z-index: 20; /* オーバーレイよりも上にする */
}
.modal-container[aria-hidden="false"] {
  overflow-y: scroll;
}
.menu-item {
  margin-top: 20px;
  text-align: center;
}
.menu-link {
  display: inline-block;
}
/* セクションのスタイル */
section {
  background-color: rgba(255, 255, 255, .1);
  background-image: repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(255, 1, 1, .1) 10px, rgba(255, 1, 1, .1) 20px );
  background-size: auto auto;
  height: 300px;
}
.section-title {
  color: #333;
  font-size: 50px;
  text-align: center;
}
.section01 {
  background-color: #e2ffc6;
}
.section02 {
  background-color: #c6ffff;
}
.section03 {
  background-color: #ffc6ff;
}
.section04 {
  background-color: #ffe2c6;
}
.section05 {
  background-color: #c6c6ff;
}
.section06 {
  background-color: #ffffc6;
}

CSSも、オーバーレイが不要であれば削除して下さい。

CSSはこれに追記していく形で解説していきます。

注意ポイント

メインコンテンツがメニューより上に重なってしまう場合は、z-indexを確認して下さい。

 

JavaScript

共通のJavaScriptはこちらになります。

window.addEventListener("DOMContentLoaded", () => {
  // ページ内リンクの取得
  const anchorLinks = document.querySelectorAll('a[href^="#"]');
  // NodeList を Array に変換
  const anchorLinksArr = Array.from(anchorLinks);
  // ハンバーガーメニューボタンの取得
  const btn = document.querySelector("#js-buttonHamburger");
  // オーバーレイの取得
  const overlay = document.querySelector("#js-overlay");
  // ページ内リンクのクリックイベントリスナー
  anchorLinksArr.forEach((link) => {
    link.addEventListener("click", (e) => {
      e.preventDefault(); // デフォルトの挙動をキャンセル
      const targetId = link.hash; // リンク先の要素のIDを取得
      const targetElement = document.querySelector(targetId); // リンク先の要素を取得
      const targetoffsetTop =
        window.pageYOffset + targetElement.getBoundingClientRect().top; // スクロール量を取得
      // メニューが開いている場合は閉じる
      if (btn.ariaExpanded == "true") {
        btn.ariaExpanded = false;
        overlay.classList.remove("active"); // オーバーレイを非表示にする
      }
      // 全てのページ内リンク要素の ariaExpanded を false にする
      anchorLinksArr.forEach((link) => {
        link.ariaExpanded = false;
      });
      MicroModal.close("modal-1"); // モーダルを閉じる
      // スムーススクロール
      window.scrollTo({
        top: targetoffsetTop,
        behavior: "smooth", // スムーススクロールを有効にする
      });
    });
  });
  // ハンバーガーメニューボタンのクリックイベントリスナー
  btn.addEventListener("click", function () {
    if (btn.ariaExpanded == "false") {
      btn.ariaExpanded = true;
      MicroModal.show("modal-1", {
        disableScroll: true, // スクロールを無効化
        awaitOpenAnimation: true, // 開くアニメーションの完了を待つ
      });
      overlay.classList.add("active"); // オーバーレイを表示する
    } else {
      btn.ariaExpanded = false;
      MicroModal.close("modal-1", {
        awaitCloseAnimation: true, // 閉じるアニメーションの完了を待つ
      });
      overlay.classList.remove("active"); // オーバーレイを非表示にする
    }
  });
  // オーバーレイのクリックイベントリスナー
  overlay.addEventListener("click", function () {
    btn.ariaExpanded = false;
    MicroModal.close("modal-1", {
      awaitCloseAnimation: true, // 閉じるアニメーションの完了を待つ
    });
    overlay.classList.remove("active"); // オーバーレイを非表示にする
  });
  // ESCキーが押された時の処理
  document.addEventListener("keydown", function (e) {
    if (e.key === "Escape") {
      btn.ariaExpanded = false;
      MicroModal.close("modal-1", {
        awaitCloseAnimation: true, // 閉じるアニメーションの完了を待つ
      });
      overlay.classList.remove("active"); // オーバーレイを非表示にする
    }
  });
});

JavaScriptも、オーバーレイが不要であれば削除して下さい。

それでは、これから6種類のハンバーガーメニューをご紹介していきます。

ここからご紹介するコードは、CSSの共通コードに追記するものだけ書きますが、全部見たい人はデモの左上にある『HTML / CSS / JavaScript』をクリックして下さい。

また、HTMLとJavaScriptに関しては、オーバーレイを削除するかどうか以外はノータッチです。

 

右からスライド(画面半分)

追記するコードはこちら。

/* メニューのスタイル */
.modal-container {
  height: 100%;
  right: -100%;
  transition: right .6s ease-in-out;
  width: 50%;
}
.modal-container[aria-hidden="false"] {
  right: 0;
  transition: right .6s ease-in-out;
}

これは、メニューを開く前はright: -100%;で、右に100%移動して見えなくしています。

そしてメニューを開くと、right: 0;で右から左に移動してきます。

そしてメニューは画面幅の半分のwidth: 50%;となっています。

デモはこちら。

See the Pen
Untitled
by junpei (@junpei-sugiyama)
on CodePen.

 

右からスライド(全画面)

これは、先ほどのwidth: 50%;width: 100%;にするだけです。

/* メニューのスタイル */
.modal-container {
  height: 100%;
  right: -100%;
  transition: right .6s ease-in-out;
  width: 100%; /* 全画面にする */
}
.modal-container[aria-hidden="false"] {
  right: 0;
  transition: right .6s ease-in-out;
}

デモはこちら。

See the Pen
Untitled
by junpei (@junpei-sugiyama)
on CodePen.

オーバーレイは有効にしてあります。

 

上からスライド(画面一部)

今度は、上からスライドさせます。

ここでは画面上部半分にしますが、実際はもっと短いと思います。

追記するコードはこちら。

/* メニューのスタイル */
.modal-container {
  height: 50%;
  top: -100%;
  transition: top .6s ease-in-out;
  width: 100%;
}
.modal-container[aria-hidden="false"] {
  top: 0;
  transition: top .6s ease-in-out;
}

右からスライドする時との違いは、以下になります。

  • righttop
  • height: 100%;height: 50%;
  • width: 50%;width: 100%;

デモはこちら。

See the Pen
Untitled
by junpei (@junpei-sugiyama)
on CodePen.

 

上からスライド(全画面)

これは、先ほどのheight: 50%height: 100%にするだけです。

/* メニューのスタイル */
.modal-container {
  height: 100%;
  top: -100%;
  transition: top .6s ease-in-out;
  width: 100%;
}
.modal-container[aria-hidden="false"] {
  top: 0;
  transition: top .6s ease-in-out;
}

デモはこちら。

See the Pen
Untitled
by junpei (@junpei-sugiyama)
on CodePen.

 

全画面フェード

フェードにする場合は、以下のコードを追記します。

/* メニューのスタイル */
.modal-container {
  height: 100%;
  opacity: 0;
  transition: opacity .6s, visibility .6s;
  visibility: hidden;
  width: 100%;
}
.modal-container[aria-hidden="false"] {
  opacity: 1;
  visibility: visible;
}

オーバーレイでも同じですが、opacityだけだと見えないだけでメインコンテンツに重なってしまうので、visibilityを書いています。

また、display: none;からdisplay: block;だとtransitionが効かないので、このような書き方をしています。

transitionが不要であれば、display: none;からdisplay: block;でもOKです。

それぞれの違いについては、以下の記事を参照下さい。

あわせて読みたい
【CSS】display: noneとopacity: 0とvisibility: hiddenの違いを解説
【CSS】display: noneとopacity: 0とvisibility: hiddenの違いを解説

続きを見る

デモはこちら。

See the Pen
Untitled
by junpei (@junpei-sugiyama)
on CodePen.

 

ハンバーガーメニュー内でスクロール

これに関しては、実はここまでの例で出来ています。

あとはメニューが縦に収まらないように長くするだけですが、このスクロールを可能にしているのは以下のコードです。

.modal-container[aria-hidden="false"] {
  overflow-y: scroll;
} 

y軸ではみ出た部分を、スクロール可能にしています。

デモはこちら。

See the Pen
Untitled
by junpei (@junpei-sugiyama)
on CodePen.

まとめ

今回は、Micromodal.jsを使ったハンバーガーメニューの作り方を解説してきました。

ハンバーガーメニューは、背景固定やオーバーレイ、リンククリックでメニューを閉じながらページ内スクロールなど、色々やることがあります。

そして案件ごとに毎回違う実装なので結構苦戦すると思いますが、ここのデモを元にすれば、大抵の実装は可能かと思います(デザインなどの調整は当然必要です)

また、今回の記事は以下のnoteを参考にさせて頂きました。

参考:ハンバーガーメニュー(micromodal.js使用)

以上になります。

この記事が役に立ったと思ったら、シェアボタンからX(旧Twitter)などにシェアすると、いいねされてフォロワーが増えたりすることがあるよ!

 

  • この記事を書いた人

じゅんぺい

37歳からWeb制作とブログ開始。Web制作歴5年目でコーディングとWordPressオリジナルテーマ制作が中心。これまで120件以上を納品。当ブログ月間最高15万PVで、370記事以上はWeb制作の技術記事。コンテンツ販売→累計売上1200万円&1500部超え。X(旧Twitter)フォロワー7200人以上。2024年3月からブログの経験を活かしてライターとしても活動を開始。

-Web制作, JavaScript