実現したいこと
・ハンバーガーメニュー
・押したらメニューを順番に表示するのを何度やっても問題なく挙動するようにしたい
前提
ハンバーガーメニューを実装中です。
ボタンを押した際に順番に表示されるようになったのですが、1度閉じて2回目に開くと文字がすでに出ている状態になります。
それを解決したいです。
該当のソースコード
HTML
1 <header> 2 <div class="head_container"> 3 <div class="head_logo"> 4 <h1> 5 タイトル 6 </h1> 7 </div> 8 <div class="head_nav"> 9 <nav> 10 <ul> 11 <li><a href="#">メニュー1</a></li> 12 <li><a href="#">メニュー2</a></li> 13 <li><a href="#">メニュー3</a></li> 14 <li><a href="#">メニュー4</a></li> 15 <li><a href="#">メニュー5</a></li> 16 <li><a href="#">メニュー6</a></li> 17 <li><a href="#"><p>メニュー7</p></a></li> 18 </ul> 19 </nav> 20 </div> 21 <div class="hamburger_box"> 22 <button class="hamburger"> 23 <span class="line"></span> 24 <span class="line"></span> 25 <span class="line"></span> 26 </button> 27 </div> 28 </div> 29 </header> 30 31 <div class="menu"> 32 <ul> 33 <li><a href="#">メニュー1</a></li> 34 <li><a href="#">メニュー2</a></li> 35 <li><a href="#">メニュー3</a></li> 36 <li><a href="#">メニュー4</a></li> 37 <li><a href="#">メニュー5</a></li> 38 <li><a href="#">メニュー6</a></li> 39 <li><a href="#"><p>メニュー7</p></a></li> 40 </ul> 41 </div> 42
SCSS
1header { 2 position: fixed; 3 width: 100%; 4 z-index: 2; 5 background-color: white; 6 .head_container { 7 height: 90px; 8 9 @media (min-width: $bp1) { 10 display: flex; 11 justify-content: center; 12 align-items: center; 13 margin: 0 0.6rem; 14 } 15 @media (min-width: $bp2) { 16 margin: 0 2rem; 17 display: flex; 18 justify-content: center; 19 align-items: center; 20 } 21 @media (min-width: $bp3) { 22 height: 90px; 23 display: flex; 24 justify-content: space-between; 25 margin: 0 4rem; 26 padding-top: 1rem; 27 } 28 .head_logo { 29 flex: 3.2; 30 display: flex; 31 align-items: center; 32 h1 { 33 a { 34 } 35 } 36 } 37 38 .head_nav { 39 flex: 6.8; 40 @media (min-width: $bp1) { 41 display: none; 42 } 43 @media (min-width: $bp2) { 44 display: none; 45 } 46 @media (min-width: $bp3) { 47 display: flex; 48 justify-content: end; 49 } 50 51 nav { 52 height: 100%; 53 54 ul { 55 padding-left: 0; 56 display: flex; 57 align-items: center; 58 height: 100%; 59 margin: 0; 60 column-gap: 1.6rem; 61 justify-content: end; 62 63 li { 64 color: #222; 65 list-style-type: none; 66 67 a { 68 color: #222; 69 font-size: 1.5rem; 70 text-decoration: none; 71 position: relative; 72 &::after { 73 background-color: currentColor; 74 bottom: -6px; 75 content: ""; 76 height: 2px; 77 left: 0; 78 position: absolute; 79 transform: scale(0, 1); 80 transform-origin: right top; 81 transition: transform 0.3s; 82 width: 100%; 83 } 84 85 &:hover::after { 86 transform-origin: left top; 87 transform: scale(1, 1); 88 } 89 90 &:hover { 91 color: #f78471; // ホバー時の色 92 } 93 } 94 95 &:last-child { 96 background-color: #f78471; 97 border-radius: 25px; 98 a { 99 color: white; 100 p { 101 margin: 0; 102 padding: 0.6rem 2rem; 103 } 104 } 105 } 106 } 107 } 108 } 109 } 110 .hamburger_box { 111 @media (min-width: $bp1) { 112 display: flex; 113 align-items: center; 114 } 115 @media (min-width: $bp2) { 116 display: flex; 117 align-items: center; 118 } 119 @media (min-width: $bp3) { 120 display: none; 121 } 122 .hamburger { 123 position: relative; 124 width: 50px; 125 height: 50px; 126 display: flex; 127 justify-content: center; 128 align-items: center; 129 border: none; 130 background: none; 131 padding: 0; 132 @media (min-width: $bp1) { 133 display: flex; 134 align-items: center; 135 } 136 @media (min-width: $bp2) { 137 display: flex; 138 align-items: center; 139 } 140 @media (min-width: $bp3) { 141 display: none; 142 } 143 cursor: pointer; 144 .line { 145 position: absolute; 146 display: block; 147 width: 50px; 148 height: 2px; 149 background-color: #000000; 150 transition: all 0.15s linear; 151 margin: 6px auto; 152 &:nth-child(1) { 153 transform: translateY(-12px) rotate(0deg); // 上の線の初期位置 154 } 155 156 &:nth-child(2) { 157 transform: translateY(0) rotate(0deg); // 真ん中の線の初期位置 158 } 159 160 &:nth-child(3) { 161 transform: translateY(12px) rotate(0deg); // 下の線の初期位置 162 } 163 } 164 165 &.open { 166 .line { 167 &:nth-child(1) { 168 transform: translateY(0) rotate(45deg); // 上の線が中央に移動して回転 169 } 170 171 &:nth-child(2) { 172 opacity: 0; // 真ん中の線を非表示 173 } 174 175 &:nth-child(3) { 176 transform: translateY(0) rotate(-45deg); // 下の線が中央に移動して回転 177 } 178 } 179 } 180 } 181 } 182 } 183} 184 185.menu { 186 ul { 187 position: relative; 188 z-index: 2; 189 display: flex; 190 flex-direction: column; // 縦方向にリストを配置 191 justify-content: center; 192 align-items: center; // リスト項目を左寄せ 193 list-style-type: none; 194 padding: 0; 195 margin: 0; 196 position: fixed; 197 top: 90px; 198 left: -100vw; // 初期位置を画面左外 199 width: 100vw; 200 height: 100vh; 201 background-color: #ffffff; // 背景色(必要に応じて変更) 202 opacity: 0; // 初期状態で非表示 203 transition: all 0.3s ease-in-out; 204 } 205 li { 206 display: flex; 207 align-items: center; 208 justify-content: center; // 左寄せ 209 padding: 1rem 2rem; // 項目の余白 210 transform: translateX(-50px); // 左にオフセット 211 opacity: 0; // 初期状態で非表示 212 transition: opacity 0.5s ease, transform 0.5s ease; // スムーズなアニメーション 213 214 a { 215 text-decoration: none; 216 font-size: 3rem; 217 color: #000000; // テキスト色 218 transition: color 0.3s ease-in-out; 219 position: relative; 220 &::after { 221 background-color: currentColor; 222 bottom: -6px; 223 content: ""; 224 height: 2px; 225 left: 0; 226 position: absolute; 227 transform: scale(0, 1); 228 transform-origin: right top; 229 transition: transform 0.3s; 230 width: 100%; 231 } 232 233 &:hover::after { 234 transform-origin: left top; 235 transform: scale(1, 1); 236 } 237 238 &:hover { 239 color: #f78471; // ホバー時の色 240 } 241 242 p { 243 margin: 0; // `<p>`タグのマージンをリセット 244 } 245 } 246 247 // 各項目の遅延設定 248 &:nth-of-type(1) { 249 transition-delay: 0.1s; 250 } 251 252 &:nth-of-type(2) { 253 transition-delay: 0.2s; 254 } 255 256 &:nth-of-type(3) { 257 transition-delay: 0.3s; 258 } 259 260 &:nth-of-type(4) { 261 transition-delay: 0.4s; 262 } 263 264 &:nth-of-type(5) { 265 transition-delay: 0.5s; 266 } 267 268 &:nth-of-type(6) { 269 transition-delay: 0.6s; 270 } 271 272 &:nth-of-type(7) { 273 transition-delay: 0.7s; 274 } 275 276 &:nth-of-type(8) { 277 transition-delay: 0.8s; 278 } 279 } 280 281 &.open { 282 ul { 283 left: 0; // メニュー全体を画面内に表示 284 opacity: 1; // 表示状態にする 285 } 286 287 li { 288 transform: translateX(0); // 左オフセットを解除 289 opacity: 1; // 表示する 290 } 291 } 292 293 @media (max-width: $bp2) { 294 ul { 295 padding: 1rem; // モバイル用の余白 296 } 297 298 li { 299 width: 100%; // モバイルではリスト幅を全体にする 300 } 301 } 302}
JS
1const hamburger = document.querySelector('.hamburger'); 2const menu = document.querySelector('.menu'); 3 4hamburger.addEventListener('click', () => { 5 toggleClasses(); 6}); 7 8 9function toggleClasses() { 10 hamburger.classList.toggle('open'); 11 menu.classList.toggle('open'); 12} 13 14const menuBtns = document.querySelectorAll('.acordion-btn'); 15const menuLists = document.querySelectorAll('.acordion'); 16 17menuBtns.forEach((element, index) => { 18 element.addEventListener('click', function () { 19 menuBtns[index].classList.toggle('is-open'); 20 menuLists[index].classList.toggle('is-open'); 21 }); 22}); 23 24// 順番にスライドインする関数 25function slideInMenuItems() { 26 menuItems.forEach((item, index) => { 27 setTimeout(() => { 28 item.style.opacity = '1'; 29 item.style.transform = 'translateX(0)'; 30 }, index * 100); // 各要素に100msの遅延 31 }); 32} 33 34// 順番にスライドアウトする関数 35function slideOutMenuItems() { 36 menuItems.forEach((item, index) => { 37 setTimeout(() => { 38 item.style.opacity = '0'; 39 item.style.transform = 'translateX(-50px)'; 40 }, index * 100); // 各要素に100msの遅延 41 }); 42}
試したこと
当初はSCSSだけでやっていましたが、明らかに動きが悪いのでJSを使ったのですが直りませんでした。
回答1件
あなたの回答
tips
プレビュー