【HTML/CSS】ハンバーガーメニューの作成|簡単なポートフォリオサイトの作成

この記事では、HTML、CSS、JavaScriptでハンバーガーメニューを実装する方法を解説します。CSSのメディアクエリでスマホ表示に対応し、JavaScriptのクリックイベントでメニューを開閉する仕組みを学びます。アイコンがアニメーションで滑らかに「×」印へ変化するCSSの使い方も分かります。

作成日: 更新日:

開発環境

  • OS: Windows10
  • Editor: Visual Studio Code
  • HTML: 5
  • CSS: 3
  • JavaScript: ES6以降

サンプルコード

/assets/css/style.css

/assets/css/style.css
1   background-color: #f5f5f5;
2   padding: 20px 0;
3   border-bottom: 1px solid #ddd;
4+  position: fixed;
5+  top: 0;
6+  left: 0;
7+  width: 100%;
8+  z-index: 1000;
9 }
10 
11 /* ヘッダー内のコンテンツを横並びに */
12   margin: 0;
13 }
14 
15+/* ハンバーガーアイコン */
16+.hamburger {
17+  display: none;
18+  flex-direction: column;
19+  justify-content: space-between;
20+  width: 28px;
21+  height: 20px;
22+  background: none;
23+  border: none;
24+  cursor: pointer;
25+  padding: 0;
26+  z-index: 1001;
27+  position: absolute;
28+  top: 20px;
29+  right: 20px;
30+}
31+
32+.hamburger span {
33+  display: block;
34+  height: 3px;
35+  background-color: #333;
36+  border-radius: 2px;
37+  transition: transform 0.3s ease, opacity 0.3s ease;
38+}
39+
40+.hamburger.active span:nth-child(1) {
41+  transform: rotate(45deg) translate(6px, 6px);
42+}
43+
44+.hamburger.active span:nth-child(2) {
45+  opacity: 0;
46+}
47+
48+.hamburger.active span:nth-child(3) {
49+  transform: rotate(-45deg) translate(6px, -6px);
50+}
51+
52+/* レスポンシブ対応 */
53 @media (max-width: 768px) {
54   /* ヘッダー:ナビを縦並びに */
55   header .container {
56   .nav-list {
57     flex-direction: column;
58     align-items: center;
59+    gap: 24px;
60+  }
61+
62+  .nav-list a {
63+    padding: 10px 20px;
64+    display: inline-block;
65   }
66 
67-  /* メインビジュアル:テキストサイズ調整 */
68   .main-text h2 {
69     font-size: 24px;
70   }
71     width: 100%;
72   }
73 
74-  /* フッター:すでに中央揃えなら変更不要 */
75-}
76+  .hamburger {
77+    display: flex;
78+  }
79+
80+  .nav {
81+    display: none;
82+    flex-direction: column;
83+    align-items: center;
84+    position: absolute;
85+    top: 70px;
86+    right: 0;
87+    width: 100%;
88+    height: 100vh;
89+    background-color: #fff;
90+    padding: 40px 0;
91+    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
92+    z-index: 1000;
93+  }
94+
95+  .nav.active {
96+    display: flex;
97+  }
98+}
99

/index.html

/index.html
1     <header>
2         <div class="container">
3             <h1 class="logo">My Portfolio</h1>
4-            <nav>
5+
6+            <!-- ハンバーガーアイコン -->
7+            <button class="hamburger" id="hamburger" aria-label="メニューを開く">
8+                <span></span>
9+                <span></span>
10+                <span></span>
11+            </button>
12+
13+            <!-- ナビゲーション -->
14+            <nav class="nav" id="nav">
15                 <ul class="nav-list">
16                     <li><a href="#about">About</a></li>
17                     <li><a href="#skills">Skills</a></li>
18         </div>
19     </footer>
20 
21+    <script>
22+        const hamburger = document.getElementById('hamburger');
23+        const nav = document.getElementById('nav');
24+        const navLinks = document.querySelectorAll('.nav-list a');
25+
26+        // メニュー開閉(ボタン)
27+        hamburger.addEventListener('click', () => {
28+            nav.classList.toggle('active');
29+            hamburger.classList.toggle('active'); // ← これを追加!
30+        });
31+
32+        // リンククリックでメニューを閉じる
33+        navLinks.forEach(link => {
34+            link.addEventListener('click', () => {
35+                nav.classList.remove('active');
36+                hamburger.classList.remove('active'); // ← これも追加!
37+            });
38+        });
39+    </script>
40+
41 </body>
42 
43 </html>
44

コード解説

変更点: ヘッダーを画面上部に固定

/assets/css/style.css
1   background-color: #f5f5f5;
2   padding: 20px 0;
3   border-bottom: 1px solid #ddd;
4+  position: fixed;
5+  top: 0;
6+  left: 0;
7+  width: 100%;
8+  z-index: 1000;
9 }

ヘッダーを常に画面の上部に表示させるため、CSSのプロパティを追加しました。position: fixed; は、要素をブラウザの表示領域(ビューポート)を基準に配置します。top: 0;left: 0; で画面の左上に配置し、width: 100%; で横幅いっぱいに広げます。z-index: 1000; は要素の重なり順を指定するプロパティで、値を大きくすることで他のコンテンツよりも手前(上)に表示させ、スクロールしてもヘッダーが隠れないようにしています。

変更点: ハンバーガーアイコンのHTML構造を追加

/index.html
1             <h1 class="logo">My Portfolio</h1>
2-            <nav>
3+
4+            <!-- ハンバーガーアイコン -->
5+            <button class="hamburger" id="hamburger" aria-label="メニューを開く">
6+                <span></span>
7+                <span></span>
8+                <span></span>
9+            </button>
10+
11+            <!-- ナビゲーション -->
12+            <nav class="nav" id="nav">
13                 <ul class="nav-list">

ハンバーガーメニューのアイコン部分をHTMLで追加しました。<button>タグを使うことで、クリックできる要素として意味的に正しくなります。class="hamburger"はCSSでデザインを適用するため、id="hamburger"はJavaScriptで操作するために付けています。中の3つの<span>タグが、アイコンの「三」の字を構成する3本線になります。

変更点: ハンバーガーアイコンの基本スタイルを定義

/assets/css/style.css
1+/* ハンバーガーアイコン */
2+.hamburger {
3+  display: none;
4+  flex-direction: column;
5+  justify-content: space-between;
6+  width: 28px;
7+  height: 20px;
8+  background: none;
9+  border: none;
10+  cursor: pointer;
11+  padding: 0;
12+  z-index: 1001;
13+  position: absolute;
14+  top: 20px;
15+  right: 20px;
16+}

ハンバーガーアイコンの基本的な見た目をCSSで作成します。display: none;でPCなどの画面幅が広いときには非表示にしておき、後のメディアクエリでスマホ表示のときだけ表示させます。flex-direction: column;justify-content: space-between;は、中の3本線(span)を縦に並べ、均等な間隔で配置するための指定です。z-index: 1001;でヘッダー(z-index: 1000)より手前に表示し、position: absolute;でヘッダー内の右上あたりに配置しています。

変更点: ハンバーガーアイコンの3本線のスタイルを定義

/assets/css/style.css
1+.hamburger span {
2+  display: block;
3+  height: 3px;
4+  background-color: #333;
5+  border-radius: 2px;
6+  transition: transform 0.3s ease, opacity 0.3s ease;
7+}

ハンバーガーアイコンの中にある3つの<span>タグ、つまり3本線のスタイルを定義します。display: block;とすることで幅や高さが指定できるようになります。transitionプロパティは、要素のスタイルが変化する際にアニメーション効果を加えるためのものです。ここでは、transform(変形)とopacity(透明度)が0.3秒かけて滑らかに変化するように設定しており、アイコンが「×」印に変わる動きがスムーズになります。

変更点: クリック時のアイコン(×印)のスタイルを定義

/assets/css/style.css
1+.hamburger.active span:nth-child(1) {
2+  transform: rotate(45deg) translate(6px, 6px);
3+}
4+
5+.hamburger.active span:nth-child(2) {
6+  opacity: 0;
7+}
8+
9+.hamburger.active span:nth-child(3) {
10+  transform: rotate(-45deg) translate(6px, -6px);
11+}

JavaScriptによってアイコンにactiveクラスが付与されたときのスタイルを定義します。これにより、3本線が「×」印に変化します。

  • span:nth-child(1)(1本目の線): transformプロパティで45度回転させ、位置を調整して「×」の右上の線になります。
  • span:nth-child(2)(2本目の線): opacity: 0;で透明にして見えなくします。
  • span:nth-child(3)(3本目の線): -45度回転させて位置を調整し、「×」の右下の線になります。

変更点: スマホ表示時のスタイル調整を開始

/assets/css/style.css
1+/* レスポンシブ対応 */
2 @media (max-width: 768px) {

CSSのメディアクエリ@media (max-width: 768px)を追加しました。このブロック内に書かれたスタイルは、ブラウザの画面幅が768px以下のとき(主にスマートフォンやタブレットでの表示)にのみ適用されます。これにより、画面サイズに応じたレスポンシブデザインを実現します。

変更点: スマホ表示時のナビゲーションリストの見た目を調整

/assets/css/style.css
1 @media (max-width: 768px) {
2   /* ヘッダー:ナビを縦並びに */
3   header .container {
4   .nav-list {
5     flex-direction: column;
6     align-items: center;
7+    gap: 24px;
8+  }
9+
10+  .nav-list a {
11+    padding: 10px 20px;
12+    display: inline-block;
13   }

スマホ表示の際、縦に並んだナビゲーションメニューの各項目の間隔を調整し、タップしやすくします。gap: 24px;で各メニュー項目の間に24pxの隙間を設けます。また、aタグにpadding(内側の余白)とdisplay: inline-block;を指定することで、文字部分だけでなくその周囲もクリック(タップ)可能な領域となり、操作性が向上します。

変更点: スマホ表示時にハンバーガーアイコンを表示

/assets/css/style.css
1 @media (max-width: 768px) {
2...
3+  .hamburger {
4+    display: flex;
5+  }

PC表示ではdisplay: none;で非表示にしていたハンバーガーアイコンを、画面幅768px以下のスマホ表示ではdisplay: flex;に切り替えて表示させます。これにより、小さい画面のときだけハンバーガーアイコンが出現するようになります。

変更点: スマホ表示時のナビゲーションメニューのスタイルを定義

/assets/css/style.css
1 @media (max-width: 768px) {
2...
3+  .nav {
4+    display: none;
5+    flex-direction: column;
6+    align-items: center;
7+    position: absolute;
8+    top: 70px;
9+    right: 0;
10+    width: 100%;
11+    height: 100vh;
12+    background-color: #fff;
13+    padding: 40px 0;
14+    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
15+    z-index: 1000;
16+  }
17+
18+  .nav.active {
19+    display: flex;
20+  }
21+}

スマホ表示におけるナビゲーションメニュー全体のスタイルを定義します。

  • .nav: 初期状態ではdisplay: none;で非表示にします。position: absolute;でヘッダーを基準に配置し、width: 100%;height: 100vh;で画面いっぱいに広がるメニューを作成します。
  • .nav.active: JavaScriptによってactiveクラスが付与されたときのスタイルです。display: flex;にすることで、非表示だったメニューが表示されるようになります。

変更点: JavaScriptでメニュー開閉機能を実装

/index.html
1     </footer>
2 
3+    <script>
4+        const hamburger = document.getElementById('hamburger');
5+        const nav = document.getElementById('nav');
6+        const navLinks = document.querySelectorAll('.nav-list a');
7+
8+        // メニュー開閉(ボタン)
9+        hamburger.addEventListener('click', () => {
10+            nav.classList.toggle('active');
11+            hamburger.classList.toggle('active'); // ← これを追加!
12+        });
13+
14+        // リンククリックでメニューを閉じる
15+        navLinks.forEach(link => {
16+            link.addEventListener('click', () => {
17+                nav.classList.remove('active');
18+                hamburger.classList.remove('active'); // ← これも追加!
19+            });
20+        });
21+    </script>
22+
23 </body>

ハンバーガーメニューの開閉を制御するJavaScriptコードを追加しました。

  • まず、getElementByIdなどで操作対象のHTML要素(アイコン、ナビゲーションメニュー、メニュー内リンク)を取得します。
  • hamburger.addEventListener('click', ...)は、ハンバーガーアイコンがクリックされたときの処理です。classList.toggle('active')を使い、ナビゲーションメニュー(nav)とアイコン(hamburger)にactiveクラスを付けたり外したりします。これにより、CSSで定義した表示・非表示やアニメーションが切り替わります。
  • navLinks.forEach(...)は、メニュー内の各リンクがクリックされたときの処理です。リンクをクリックしたら、classList.remove('active')activeクラスを削除し、メニューが閉じるようにしています。

おわりに

お疲れ様でした。今回はHTML、CSS、JavaScriptを組み合わせて、レスポンシブ対応のハンバーガーメニューを実装しました。CSSのメディアクエリでスマホ表示のスタイルを定義し、JavaScriptのclassList.toggleactiveクラスを付け外しすることで、メニューの開閉やアイコンのアニメーションを制御する仕組みが理解できたかと思います。特に、クリックイベントをきっかけにCSSの状態を切り替えるという流れは、動きのあるWebサイトを作る上で頻繁に使う重要なテクニックです。

【HTML/CSS】ハンバーガーメニューの作成|簡単なポートフォリオサイトの作成 | いっしー@Webエンジニア