Web制作 JavaScript

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

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

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

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

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

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

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

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

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

続きを見る

 

完全無料のプログラミングスクール『ZeroPlus Gate』
30日間でWeb制作を学べる無料のプログラミングスクールがこちら
  • 30日間でWeb制作を学べる
  • 完全無料
  • 現役エンジニアへの質問無制限
  • オンラインの動画学習なので時間場所を問わず勉強可能
  • 最大4回の学習サポート面談
  • 受付は1日25名までの先着制
無料なのに専属のメンターが付き、現役エンジニアへの質問も無制限という破格のサービスです。
いきなり数十万するプログラミングスクールは厳しい・・・という人のお試しに最適。
現在は無料ですがいつ有料になるか分からないので、気になる方はお早めに👇

\ 完全無料 /

ZeroPlus Gate公式サイト

先着1日25名まで!

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使用)

以上になります。

 

Web制作おすすめ教材と案件獲得サービス
当ブログではWeb制作学習におすすめの教材を厳選してご紹介しています。
こちらの記事を参考に教材を購入して成果を出している人もたくさんいるので、自分に必要な教材を探してみて下さい。
また、学習面だけでなく営業面である案件獲得サービスもご紹介しています。
スキルが身についても仕事がなければ意味がないので、営業に不安がある人はこちらの記事をぜひ参考にしてみて下さい。
この記事を参考にスキルと営業力を身につけて稼げるようになりましょう!

-Web制作, JavaScript