はじめに
今回から、JavaScriptのイベント処理→条件分岐の順番で学んでいきます。学ぶ順番の理由は以下の通りです。
①イベント処理から学ぶ理由
- イベント処理は、ユーザーとのインタラクション(クリック、ホバー、キーボード入力など)を管理するために必要です。
- 実際の動作が視覚的に確認できるため、学習が直感的に理解しやすく、イベント処理から学ぶことで、ユーザーインターフェースの基本的なインタラクションを扱えるようになります。
②イベント処理で学ぶ内容
- ハンバーガーメニューの開閉アニメーション、スムーズスクロールを作りたい。
PC版ヘッダーメニューのコード解説
最初はPCで見ると仮定して、ヘッダーのナビゲーションは全て表示するように考えます。
HTML5のコード解説
<!-- ヘッダー -->
<header class="header wrapper">
<div class="logo"><a href="#">LOGO</a></div>
<nav class="pc-nav">
<ul>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
</ul>
</nav>
<nav class="sp-nav">
<ul>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
</ul>
</nav>
</header>
<!-- /ヘッダー -->
- pc-navとsp-navの2つに分けて、それぞれサイズに合わせて表示できるように考えました。
CSS3のコード解説
/* ヘッダー */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
}
.logo {
font-size: 35px;
font-weight: bold;
}
.header ul {
display: flex;
gap: 30px;
}
.sp-nav {
display: none;
}
- ヘッダーとナビゲーションメニューは、display: flex;で横並びにし、ワイヤーフレーム通りに制作しました。.sp-navはdisplay: none;を設定し、レスポンシブ時のナビゲーションメニューは非表示しました。
レスポンシブ版ヘッダーメニューのコード解説
次にレスポンシブに対応した場合を考えていきます。ナビゲーションメニューは、三本線にまとめ、非表示の準備をします。
HTML5のコード解説
<!-- ヘッダー -->
<header class="header wrapper">
<div class="logo"><a href="#">LOGO</a></div>
<nav class="pc-nav">
<ul>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
</ul>
</nav>
<nav class="sp-nav">
<ul>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
<li><a href="#">MENU</a></li>
</ul>
</nav>
<!-- ハンバーガーメニュー -->
<div id="hamburger">
<span></span>
</div>
<!-- /ハンバーガーメニュー -->
</header>
<!-- /ヘッダー -->
- .sp-navの下に#hamburgerを設置し、spanタグで三本線を表現しています。
CSS3のコード解説
/* ハンバーガーメニュー */
@media screen and (max-width: 640px) {
.header ul {
display: none;
}
.sp-nav {
z-index: 1;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
display: block;
width: 100%;
background: rgba(255, 68, 0, 0.8);
opacity: 0;
transform: translateY(-100%);
transition: opacity 0.3s ease-in-out, left 0.3s ease-in-out;
}
#hamburger {
position: relative;
display: block;
width: 30px;
height: 25px;
margin: 0 0 0 auto;
cursor: pointer;
z-index: 999;
}
#hamburger span,
#hamburger::before,
#hamburger::after {
position: absolute;
left: 0;
display: block;
width: 100%;
height: 2px;
background-color: #333;
transition: all 0.3s ease-in-out; /* 線のアニメーション */
}
#hamburger span {
position: absolute;
top: 50%;
left: 0;
display: block;
width: 100%;
height: 2px;
background-color: #333;
transform: translateY(-50%);
}
#hamburger::before {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 2px;
background-color: #333;
}
#hamburger::after {
content: "";
display: block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 2px;
background-color: #333;
}
- .hamburger-active: このクラスが追加されたとき、ハンバーガーメニューの線が45度回転し、クロスするアニメーションを実現します。JavaScriptでこのクラスをトグルすることで、メニューの開閉時にハンバーガーアイコンが変化します。
- .sp-nav.open: メニューが開いている状態を表現するクラスで、opacity: 1とtransform: translateY(0)により、ナビゲーションメニューが表示されます。
開閉ハンバーガーメニューのコード解説
最後に、ハンバーガーメニューをクリック時の動きとその他アニメーションを考えます。
CSS3のコード解説
/* メニューが開いたときのクロススタイル */
.hamburger-active #hamburger span {
transform: rotate(45deg); /* 中央の線を45度回転 */
}
.hamburger-active #hamburger::before {
top: 50%;
transform: rotate(45deg); /* 上の線を45度回転させてクロス */
}
.hamburger-active #hamburger::after {
bottom: 50%;
transform: rotate(-45deg); /* 下の線を-45度回転させてクロス */
}
.sp-nav.open {
opacity: 1;
transform: translateY(0);
visibility: visible;
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out, visibility 0s; /* visibilityは即表示 */
}
.sp-nav ul {
padding: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
}
.sp-nav li {
margin: 0;
padding: 0;
}
.sp-nav li span {
font-size: 15px;
color: #333;
}
.sp-nav li a,
.sp-nav li span {
display: block;
padding: 20px 0;
}
}
- ハンバーガーメニューは、レスポンシブ時に表示するよう設定します。そのため、.pc-menuは非表示にし、transform: rotate();で上下にそれぞれ45度と-45度回転してクロスするように見せています。
- メニューが閉じているときは、opacity: 0 と transform: translateY(-100%) によって画面上部に隠れています。
- メニューが開くと、opacity: 1 と transform: translateY(0) によってメニューがフェードインしながらスライドして表示されます。
- レスポンシブ時、ハンバーガーメニューがクリックされると、ナビゲーションメニュー(.sp-nav)が表示され、display: flex で縦方向にリストが並びます。
JavaScriptのコード解説
document.getElementById("hamburger").addEventListener("click", function () {
// ハンバーガーメニューのクラスをトグル
document.querySelector(".sp-nav").classList.toggle("open");
// ハンバーガーのクロス用クラスをトグル
document.body.classList.toggle("hamburger-active");
});
- document.querySelector(".sp-nav").classList.toggle("open");では、ここでは、sp-nav要素に openクラスを追加または削除しています。このクラスが追加されると、CSSで設定されたopacityや transformのアニメーションによってメニューが開閉します。
- document.body.classList.toggle("hamburger-active");では、body要素にhamburger-activeクラスを追加または削除しています。このクラスは、CSSで設定した #hamburger spanや#hamburger::before、#hamburger::afterのアニメーションを制御し、ハンバーガーアイコンが3本線からクロス状に変化します。
- .sp-navにopen クラスがトグルされ、メニューがスライドイン/スライドアウトするアニメーションが実行されます。bodyにhamburger-activeクラスがトグルされ、ハンバーガーメニューのアイコンがクロス形に変わります。
全体のコード一覧
See the Pen JavaScriptのイベント処理で、ハンバーガーメニューの開閉アニメーションについて考えてみる by Uka Suzuki (@uukasuzuki_) on CodePen.
疑問
今回の記事を通して、3点疑問があります。今後の知見を深めるため、解決策やアドバイス、ご意見など頂けると幸いですm(_ _)m
- ハンバーガーメニューの三本線をクロスさせるする時、微妙にずれている気がします。綺麗にクロスするにはどうすればいいでしょうか?角度や横幅など考えましたが、悩んでいます。
- ハンバーガーメニューをクリックした時、背景色をゆっくり右からフェードインで表示させ、また閉じる時にも同様にゆっくりフェードアウトさせたいです。
- スムーズに情報伝達を発信するために、UIパーツを作る時にコーディングで気を付ける点はありますか?
まとめ
一からハンバーガーメニューをレスポンシブ対応用に制作しました。クリック時の操作性とスムーズさを考えるのが、一番難しかったです。