【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.css1 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.html1 <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.css1 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.html1 <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.css1+/* ハンバーガーアイコン */ 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.css1+.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.css1+.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.css1+/* レスポンシブ対応 */ 2 @media (max-width: 768px) {
CSSのメディアクエリ@media (max-width: 768px)を追加しました。このブロック内に書かれたスタイルは、ブラウザの画面幅が768px以下のとき(主にスマートフォンやタブレットでの表示)にのみ適用されます。これにより、画面サイズに応じたレスポンシブデザインを実現します。
変更点: スマホ表示時のナビゲーションリストの見た目を調整
/assets/css/style.css1 @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.css1 @media (max-width: 768px) { 2... 3+ .hamburger { 4+ display: flex; 5+ }
PC表示ではdisplay: none;で非表示にしていたハンバーガーアイコンを、画面幅768px以下のスマホ表示ではdisplay: flex;に切り替えて表示させます。これにより、小さい画面のときだけハンバーガーアイコンが出現するようになります。
変更点: スマホ表示時のナビゲーションメニューのスタイルを定義
/assets/css/style.css1 @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.html1 </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.toggleでactiveクラスを付け外しすることで、メニューの開閉やアイコンのアニメーションを制御する仕組みが理解できたかと思います。特に、クリックイベントをきっかけにCSSの状態を切り替えるという流れは、動きのあるWebサイトを作る上で頻繁に使う重要なテクニックです。