【JS&CSS】ハンバーガーメニューの作り方

【アイキャッチ画像】ハンバーガーメニューの実装方法

本記事では、ホームページなどでよく見かける画面右(左)上の三本線アイコン(ハンバーガーメニュー)の実装方法(HTML/CSS/JavaScriptコード)を、実装例とともに紹介します。

実装例

右上の三本線アイコンをクリックすると、中央にフワッとメニューが表示されます。

自分の学習・メモ用がメインですが、プログラミング学習初心者の参考になればとも思います!

目次

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

以下の3ステップで、実装方法を解説&コードを公開しています。

  • ハンバーガーメニューのアイコン作成
  • アイコンをクリックしてメニューを表示
  • 画面幅に合わせて表示を変える

STEP

ハンバーガーメニューのアイコンを作る

まずはアイコンの作り方です。(メニュー表示は次項)

三本線アイコンをクリック(タップ)すると、「✖」マークに変化します。

「✖」マークをクリック(タップ)すると、再び三本線アイコンに戻ります。

実装例(メニューは表示されません)
HTML / CSS / JavaScript コード
<div class="hamburger-menu">
    <div class="line"></div>
    <div class="line"></div>
    <div class="line"></div>
</div>
.hamburger-menu {
  width: 30px;
  height: 22px;
  position: absolute;
  top: 20px;
  right: 20px;
  cursor: pointer;
}

.line {
  background-color: black;
  height: 4px;
  width: 100%;
  position: absolute;
  transition: all 0.3s;
}

.line:nth-of-type(1) {
  top: 0;
}

.line:nth-of-type(2) {
  top: 50%;
  transform: translateY(-50%);
}

.line:nth-of-type(3) {
  bottom: 0;
}

.hamburger-menu.active > .line:nth-of-type(1) {
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
}

.hamburger-menu.active > .line:nth-of-type(2) {
  display: none;
}

.hamburger-menu.active > .line:nth-of-type(3) {
  top: 50%;
  transform: translateY(-50%) rotate(-45deg);
}
const hamburgerMenu = document.querySelector('.hamburger-menu');
hamburgerMenu.addEventListener('click', () => {
    hamburgerMenu.classList.toggle('active');
});

三本線アイコンの作り方

本実装例の三本線アイコンは、以下のHTMLとCSSで表現しています。

<div class="hamburger-menu">
    <div class="line"></div>
    <div class="line"></div>
    <div class="line"></div>
</div>
.line {
  background-color: black;
  height: 4px;
  width: 100%;
  position: absolute;
}

.line:nth-of-type(1) {
  top: 0;
}

.line:nth-of-type(2) {
  top: 50%;
  transform: translateY(-50%);
}

.line:nth-of-type(3) {
  bottom: 0;
}

positionプロパティを使うことで、親要素(hamburger-menuクラスが付いたdiv要素)に対し、子要素(各ライン)を指定の位置に配置できます。

ライン1つ目

top: 0;→ 親要素の上端に配置

ライン2つ目

top: 50%;&transform: translateY(-50%); → 親要素の中央に配置

ライン3つ目

bottom: 0;→ 親要素の下端に配置

クリック時のアニメーション

まずアイコンをクリックすることで、アイコン要素にactiveクラスを付け外しできるJavaScriptを実装します。

hamburgerMenu.addEventListener('click', () => {
    hamburgerMenu.classList.toggle('active');
});

次にCSSで、アイコン要素にactiveクラスが付いたときのスタイルを適用します。

.hamburger-menu.active > .line:nth-of-type(1) {
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
}

.hamburger-menu.active > .line:nth-of-type(2) {
  display: none;
}

.hamburger-menu.active > .line:nth-of-type(3) {
  top: 50%;
  transform: translateY(-50%) rotate(-45deg);
}

真ん中のラインはdisplay: none;で非表示にします。
上端と下端のラインは、top: 50%;&transform: translateY(-50%);で真ん中に配置し、
rotate(45deg)&rotate(-45deg)で逆方向に回転させると、「✖」アイコンが作れます。

また、アニメーションに動きを付けるため、transitionプロパティを合わせて適用しています。

.line {
  transition: all 0.3s;
}

このプロパティにより、0.3秒かけて前述のスタイルが適用されるようになります。

STEP

アイコンをクリックしてメニューを表示させる

次に、アイコンをクリックすることで画面中央にメニューをフワッと表示させる方法です。

再度「✖」アイコンをクリックするとメニューが閉じます。

HTML / CSS / JavaScript コード
<div class="hamburger-menu">
    <div class="line"></div>
    <div class="line"></div>
    <div class="line"></div>
</div>
<nav class="nav-menu">
  <a href="#">メニュー1</a>
  <a href="#">メニュー2</a>
  <a href="#">メニュー3</a>
</nav>
.hamburger-menu {
  width: 30px;
  height: 22px;
  position: absolute;
  top: 20px;
  right: 20px;
  cursor: pointer;
}

.line {
  background-color: black;
  height: 4px;
  width: 100%;
  position: absolute;
  transition: all 0.3s;
}

.line:nth-of-type(1) {
  top: 0;
}

.line:nth-of-type(2) {
  top: 50%;
  transform: translateY(-50%);
}

.line:nth-of-type(3) {
  bottom: 0;
}

.hamburger-menu.active > .line:nth-of-type(1) {
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
}

.hamburger-menu.active > .line:nth-of-type(2) {
  display: none;
}

.hamburger-menu.active > .line:nth-of-type(3) {
  top: 50%;
  transform: translateY(-50%) rotate(-45deg);
}

.nav-menu {
  display: none;
  flex-direction: column;
  position: absolute;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
  align-items: center;
  justify-content: center;
  padding: 8px;
  width: 200px;
  background-color: #fff;
  border: 1px solid #ccc;
  opacity: 0;
}

.nav-menu.active {
  display: flex;
  animation: fadeIn 0.5s forwards;
}

.nav-menu a {
  text-decoration: none;
  color: black;
  padding: 5px;
  margin: 5px;
}

@keyframes fadeIn {
  0% {
    top: 45%;
    opacity: 0;
  }
  
  100% {
    top: 50%;
    opacity: 1;
  }
}
const hamburgerMenu = document.querySelector('.hamburger-menu');
const navMenu = document.querySelector('.nav-menu');
hamburgerMenu.addEventListener('click', () => {
    hamburgerMenu.classList.toggle('active');
    navMenu.classList.toggle('active');
});

メニューの作り方

本実装例のメニューは、以下のHTMLとCSSで表現しています。

<nav class="nav-menu">
  <a href="#">メニュー1</a>
  <a href="#">メニュー2</a>
  <a href="#">メニュー3</a>
</nav>
.nav-menu {
  display: none;
  flex-direction: column;
  position: absolute;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
  align-items: center;
  justify-content: center;
  padding: 8px;
  width: 200px;
  background-color: #fff;
  border: 1px solid #ccc;
  opacity: 0;
}

.nav-menu.active {
  display: flex;
  animation: fadeIn 0.5s forwards;
}

.nav-menu a {
  text-decoration: none;
  color: black;
  padding: 5px;
  margin: 5px;
}

メニューの配置は、アイコンと同じくpositionプロパティを使って、画面中央にくるよう配置しています。
後述のアニメーションの関係で、top: 45%;と若干上側に配置しています。

また、アイコンクリック前は表示させたくないので、display: none;で非表示にし、activeクラスが付いたときにdisplay: flex;で表示させています。
opacity: 0;にしているのは後述のアニメーションの関係です。

フワッと表示させる方法

アイコンをクリック時、メニューを少し上から下に向かってフワッと表示させるには、CSSのkeyframesプロパティを使います。

まずJavaScriptで、アイコンクリック時にメニュー要素にもactiveクラスを付け外しできるよう実装します。

hamburgerMenu.addEventListener('click', () => {
    hamburgerMenu.classList.toggle('active');
    navMenu.classList.toggle('active');
});

次にCSSで、メニュー要素にactiveクラスが付いたときのスタイルを適用します。

.nav-menu.active {
  display: flex;
  animation: fadeIn 0.5s forwards;
}

display: flex;でメニューが表示され、fadeInというanimationが0.5秒かけて行われ、アニメーション終了後の形でとどまります。

fadeInアニメーションは以下の通り設定しています。

@keyframes fadeIn {
  0% {
    top: 45%;
    opacity: 0;
  }
  
  100% {
    top: 50%;
    opacity: 1;
  }
}

これにより、0.5秒かけてメニューの位置が5%下がり(top: 45%;top: 50%;)、
フワッと表示(opacity: 0;opacity: 1;)されるようになります。

STEP

デバイス(PC/スマホ)に応じて表示を変える

以上でハンバーガーメニューは完成ですが、基本的にハンバーガーメニューは画面幅が小さいモバイルなどで適用され、PCなど広い画面幅では使われません。(わざわざ三本線アイコンにせず、ヘッダーなどにメニューをそのまま表示させます。)

そこで最後に、画面幅に応じて表示を変える実装方法を紹介します。

実装例

画面幅を800px以下にすると、ハンバーガーメニューが表示されます。

HTML / CSS / JavaScript コード
<div class="container">
  <div class="header">
    <div class="logo">仮ロゴ</div>
    <nav class="pc-menu">
      <ul>
        <li><a href="#">メニュー1</a></li>
        <li><a href="#">メニュー2</a></li>
        <li><a href="#">メニュー3</a></li>
      </ul>
    </nav>
    <div class="mobile-menu hamburger-menu">
      <div class="line"></div>
      <div class="line"></div>
      <div class="line"></div>
    </div>
  </div>
  <nav class="nav-menu">
    <a href="#" class="menu-link">メニュー1</a>
    <a href="#" class="menu-link">メニュー2</a>
    <a href="#" class="menu-link">メニュー3</a>
  </nav>
</div>
/* ==== ヘッダーのスタイル ==== */
.header {
  width: 100%;
  height: 80px;
  background: rgba(0, 0, 0, .2);
  display: flex;
  justify-content: space-between;
}

.header .logo {
  width: 20%;
  height: 80px;
  text-align: center;
  line-height: 80px;
  font-size: 20px;
  font-weight: 600;
  background: skyblue;
}

.header nav {
  width: 50%;
}

.header ul {
  width: 100%;
  display: flex;
  list-style: none;
  padding: 0;
  margin: 0;
}

.header ul li {
  width: 33%;
}

.header a {
  display: block;
  width: 100%;
  line-height: 80px;
  text-align: center;
  text-decoration: none;
  color: black;
}

/* ==== ハンバーガーメニューのスタイル ==== */
.hamburger-menu {
  display: none;
  width: 30px;
  height: 22px;
  position: relative;
  top: 50%;
  right: 20px;
  transform: translateY(-50%);
  cursor: pointer;
}

.line {
  background-color: black;
  height: 4px;
  width: 100%;
  position: absolute;
  transition: all 0.3s;
}

.line:nth-of-type(1) {
  top: 0;
}

.line:nth-of-type(2) {
  top: 50%;
  transform: translateY(-50%);
}

.line:nth-of-type(3) {
  bottom: 0;
}

.hamburger-menu.active > .line:nth-of-type(1) {
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
}

.hamburger-menu.active > .line:nth-of-type(2) {
  display: none;
}

.hamburger-menu.active > .line:nth-of-type(3) {
  top: 50%;
  transform: translateY(-50%) rotate(-45deg);
}

.nav-menu {
  display: none;
  flex-direction: column;
  position: absolute;
  top: 45%;
  left: 50%;
  transform: translate(-50%, -50%);
  align-items: center;
  justify-content: center;
  padding: 8px;
  width: 200px;
  background-color: #fff;
  border: 1px solid #ccc;
  opacity: 0;
}

.nav-menu.active {
  display: flex;
  animation: fadeIn 0.5s forwards;
}

.nav-menu a {
  text-decoration: none;
  color: black;
  padding: 5px;
  margin: 5px;
}

@keyframes fadeIn {
  0% {
    top: 45%;
    opacity: 0;
  }
  
  100% {
    top: 50%;
    opacity: 1;
  }
}

@media (max-width: 800px) {
  .hamburger-menu {
    display: block;
  }

  .pc-menu {
    display: none;
  }
}
const hamburgerMenu = document.querySelector('.hamburger-menu');
const navMenu = document.querySelector('.nav-menu');
hamburgerMenu.addEventListener('click', () => {
    hamburgerMenu.classList.toggle('active');
    navMenu.classList.toggle('active');
});

固定表示ヘッダーの作り方

以下記事で詳しく紹介しています。

画面幅に応じて表示を変える方法(レスポンシブウェブデザイン)

メディアクエリと呼ばれるCSSの記法を使って実装します。

@media (max-width: 800px) {
  .hamburger-menu {
    display: block;
  }

  .pc-menu {
    display: none;
  }
}

これにより、画面幅が800px以下の場合にハンバーガーメニューが表示され、800pxを超えるとヘッダーにそのままメニューが表示されるようになります。

詳細は、以下記事で詳しく紹介しています。

まとめ

以上、ハンバーガーメニューの実装方法について紹介しました。
ウェブデザインの参考になれば嬉しいです。


当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次