【実践編】JavaScriptでハンバーガーメニューを作ろう

ホームページを作成する際、レスポンシブに欠かせないのがハンバーガーメニューです。

jQueryを使用して作ることも多いですが、今回はJavaScriptでの作成方法を紹介します。

ぜひ、最後まで見ていってください!

目次

ハンバーガーメニューの実装

今回はこのようなシンプルなハンバーガーメニューを作っていきます。

画面幅が768px以下になった時に表示されるようにメディアクエリを設定しています。

See the Pen ハンバーガーメニュー by 株式会社iris (@gxzlclhr-the-bashful) on CodePen.

HTMLの解説

最低限必要なものはハンバーガーのアイコン用のspanタグとメニュー項目が入ったナビゲーションメニューです。

<div class="container">
  <header>
    <div class="header__inner">
      <h1 class="header__logo">
        <a href="">ロゴ</a>
      </h1>
      <div class="header__hamburger">
        <button class="hamburger">
          <span></span>
          <span></span>
          <span></span>
        </button>
      </div>
      <nav class="header__nav nav" id="js-nav">
        <div class="nav__inner">
          <ul class="nav__list">
            <li class="nav__item">
              <a class="nav__link" href="#">メニュー1</a>
            </li>
            <li class="nav__item">
              <a class="nav__link" href="#">メニュー2</a>
            </li>
            <li class="nav__item">
              <a class="nav__link" href="#">メニュー3</a>
            </li>
            <li class="nav__item">
              <a class="nav__link" href="#">メニュー4</a>
            </li>
          </ul>
        </div>
      </nav>
    </div>
  </header>
</div>

CSSの解説

次にCSSでスタイルを設定します。

こちらがCSSの完成版です。

header {
    display: block;
    z-index: 10;
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    width: 100%;
    height: 70px;
    background-color: #e9dfe2;
}

/* ロゴ */
.header__logo {
    width: 100%;
    max-width: 120px;
    background: #c87c7c;
}
.header__logo a {
    display: block;
    width: 100%;
    height: auto;
    padding: 20px 40px;
    color: #fff;
}
.header__hamburger {
    z-index: 100;
    position: absolute;
    top: 0;
    right: 0;
    width: 70px;
    height: 100%;
}
@media screen and (min-width:768px) {
    .header__hamburger {
        display: none;
    }
}

/* ナビゲーションメニュー */
.header__nav {
    display: flex;
    z-index: 10;
    position: absolute;
    top: 0;
    right: -100%;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    height: 100%;
    background: transparent;
    font-weight: 700;
    opacity: 0;
    transition: 0.6s;
    margin-top: 70px;
}
@media screen and (min-width:768px) {
    .header__nav {
        position: static;
        height: 100%;
        opacity: initial;
        align-items: flex-start;
        width: fit-content;
        justify-content: center;
        margin-top: 0;
    }
}
.header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: inherit;
    padding: 13px 20px;
}

.nav {
    padding-top: 70px;
    padding-bottom: 70px;
}
@media screen and (min-width:768px) {
    .nav {
        padding-top: 16px;
        padding-bottom: 16px
    }
}
.nav__list {
    display: block;
    width: 100%;
    padding-right: 20px;
    padding-left: 20px;
}
@media screen and (min-width:768px) {
    .nav__list {
        display: flex;
        padding-right: 0;
    }
}
.nav__item {
    position: relative;
    width: 100%;
}
.nav__link {
    color: #535353;
    display: block;
    width: 100%;
    height: 100%;
    padding: 20px;
    text-align: center;
}

/* ハンバーガーメニュー */
.hamburger {
    position: relative;
    width: inherit;
    height: inherit;
    margin: 0;
    border: 1px solid #c87c7c;
    cursor: pointer;
}
.hamburger span {
    display: block;
    position: relative;
    left: 50%;
    width: 30px;
    height: 2px;
    transform: translateX(-50%);
    background: #c87c7c;
    transition: all 0.4s;
}
.hamburger span:nth-of-type(1) {
    top: -10%;
}
.hamburger span:nth-of-type(2) {
    top: 0;
}
.hamburger span:nth-of-type(3) {
    top: 10%;
}
.hamburger.is-active span:nth-of-type(1) {
    top: 0;
    transform: translateX(-50%) rotate(225deg);
}
.hamburger.is-active span:nth-of-type(2) {
    opacity: 0;
}
.hamburger.is-active span:nth-of-type(3) {
    top: -4px;
    transform: translateX(-50%) rotate(-225deg);
}

/* ハンバーガーメニューが開いた時 */
.header__nav.is-active {
    position: fixed;
    top: 0;
    right: 0;
    background: #f5eded;
    opacity: 1;
    transition: 1s;
}

768px以上の画面幅ではハンバーガーメニューを表示させないために、header__hamburgerdisplay: none;を当て、768px以下になるとdisplay: block;を当てます。

ロゴとハンバーガーメニューを横並びにするためにheader__innerdisplay: flex;を当てます。

ハンバーガーのアイコンは3本の平行線が縦に並んだものなので以下のようにスタイルを当ててみましょう。

.hamburger {
    position: relative;
    width: inherit;
    height: inherit;
    margin: 0;
    border: 1px solid #c87c7c;
    cursor: pointer;
}
.hamburger span {
    display: block;
    position: relative;
    left: 50%;
    width: 30px;
    height: 2px;
    transform: translateX(-50%);
    background: #c87c7c;
    transition: all 0.4s;
}
.hamburger span:nth-of-type(1) {
    top: -10%;
}
.hamburger span:nth-of-type(2) {
    top: 0;
}
.hamburger span:nth-of-type(3) {
    top: 10%;
}

クリックされるとis-activeというクラス名を付与し、ハンバーガーの3本線をバツに変更する設定が以下になります。

.hamburger.is-active span:nth-of-type(1) {
    top: 0;
    transform: translateX(-50%) rotate(225deg);
}
.hamburger.is-active span:nth-of-type(2) {
    opacity: 0;
}
.hamburger.is-active span:nth-of-type(3) {
    top: -4px;
    transform: translateX(-50%) rotate(-225deg);
}

ハンバーガーメニューのアイコンがクリックされる前はハンバーガーメニューを右側に隠すためにright: -100%;を指定しておきます。

.header__nav {
    display: flex;
    z-index: 10;
    position: absolute;
    top: 0;
    right: -100%;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    height: 100%;
    background: transparent;
    font-weight: 700;
    opacity: 0;
    transition: 0.6s;
    margin-top: 70px;
}

ハンバーガーのアイコンがクリックされてis-activeクラスが付与されるとスライドされてメニューが表示されるように以下のようright: 0;に設定します。

.header__nav.is-active {
    position: fixed;
    top: 0;
    right: 0;
    background: #f5eded;
    opacity: 1;
    transition: 1s;
}

JavaScriptの解説

JavaScriptを使って、ハンバーガーアイコンがクリックされた時にメニューが表示されるように設定します。

document.addEventListener('DOMContentLoaded', function () {
    const hamburger = document.querySelector('.hamburger');
    const headNav = document.querySelector('#js-nav');

    hamburger.addEventListener('click', () => {
        if (hamburger.classList.contains('is-active')) {
        hamburger.classList.remove('is-active');
        headNav.classList.remove('is-active')
        } else {
        hamburger.classList.add('is-active');
        headNav.classList.add('is-active')
        }
    });

    headNav.addEventListener('click', () => {
        hamburger.classList.remove('is-active');
        headNav.classList.remove('is-active')
    });
});

ハンバーガーアイコンをクリックするというイベントを登録するにはaddEventListenerを使用します。

まず、querySelectorでhamburgerというクラスを取得します。

const hamburger = document.querySelector('.hamburger');

hamburgerをクリックした時にis-activeというクラス名がなければ付与し、あれば外すというものをif文を使って以下のように記述します。

hamburger.addEventListener('click', () => {
        if (hamburger.classList.contains('is-active')) {
        hamburger.classList.remove('is-active');
        headNav.classList.remove('is-active')
        } else {
        hamburger.classList.add('is-active');
        headNav.classList.add('is-active')
        }
    });

toggleを使うとクラスの付け外しをすることができるので、こちらを使用することも可能です。

hamburger.addEventListener('click', function() {
     hamburger.classList.toggle('is-active'); 
  });

次にナビゲーションメニューを取得します。

const headNav = document.querySelector('#js-nav');

先ほどのコードに以下のように追記するとナビゲーションメニューにもis-activeを付与することができるようになります。

const hamburger = document.querySelector('.hamburger');
    const headNav = document.querySelector('#js-nav');

    hamburger.addEventListener('click', () => {
        if (hamburger.classList.contains('is-active')) {
        hamburger.classList.remove('is-active');
        headNav.classList.remove('is-active')
        } else {
        hamburger.classList.add('is-active');
        headNav.classList.add('is-active')
        }
    });

最後にハンバーガーメニューを表示させた後、ナビゲーションメニューの範囲をクリックするとハンバーガーメニューを閉じるように設定します。

headNav.addEventListener('click', () => {
        hamburger.classList.remove('is-active');
        headNav.classList.remove('is-active')
    });

まとめ

今回は基本のJavaScriptを使ったハンバーガーメニューの作り方を解説してきました。

いかがでしたでしょうか?

色々と応用してハンバーガーのアイコンのアニメーションを変えてみたり、CSSでカスタマイズしてみてくださいね!

他の投稿ではHTML&CSSの基礎知識やWordPressについても解説していますので、ぜひチェックしてみてください!

コメント

コメントする

目次