スマホ表示のハンバーガーアイコンクリック時にグローバルナビゲーションのメニューを表示させる
ヘッダのグローバルメニューは横幅が広く、スマートフォン(スマホ)画面では、横一列で表示させると窮屈な印象を与えてしまいます。
よって、スマートフォン表示では、初期表示時にはグローバルメニューを非表示にしています。
スマートフォン表示時は右上に配置したハンバーガーアイコン(三本線)のボタンをクリックすることでグローバルナビのメニューが縦に表示されるようにします。
完成系のイメージ:
HTMLやCSSだけでは、「ボタンをクリックしたら動く」といった、ユーザーの操作に反応するような動きを作ることはできません。
そのような動き(仕組み)を作るには、JavaScriptで処理を実装する必要があります。(JavaScriptについての解説は、こちらの記事を参照ください。)
コーディング
JavaScriptをコーディングするための準備をします。
sample-siteフォルダの配下にjsフォルダを作成し、jsフォルダにindex.jsを配置します。
sample-site
├── index.html
├── css
├──├── style.css
├──├── reset.css
├── js
├──├── index.js
index.htmlに以下の修正を加えます。
- index.jsファイルの読み込み
- 表示されたグローバルナビを閉じるための×ボタンを配置
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>サンプルサイト</title>
<link rel="stylesheet" media="all" href="css/style.css" />
<link rel="stylesheet" media="all" href="css/reset.css" />
<script src="./js/index.js"></script> <!-- この行を追加 -->
</head>
<body>
<header class="header">
<div class="container">
<div class="header-top">
<h1 class="logo"><a href="index.html">Sample</a></h1>
<label for="toggle" class="toggle-btn-open">
<span></span>
<span></span>
<span></span>
</label>
<div class="toggle-btn-close"></div> <!-- この行を追加 -->
<div class="tel">TEL:00-0000-0000</div>
</div>
<div class="nav">
<ul class="nav-list" role="list">
<li class="nav-item"><a href="#">ホーム</a></li>
<li class="nav-item"><a href="#">会社概要</a></li>
<li class="nav-item"><a href="#">事業内容</a></li>
<li class="nav-item"><a href="#">採用情報</a></li>
<li class="nav-item"><a href="#">お問い合わせ</a></li>
</ul>
</div>
</div>
</header>
<div>
<img src="img/mainimg.png" alt="メイン画像" class="main-img">
</div>
<div class="content">
<div class="container">
<div class="sidebar">
<ul role="list">
<li><a href="#"><img src="img/banner.png" alt="バナー画像" class="banner"></a></li>
<li><a href="#"><img src="img/banner.png" alt="バナー画像" class="banner"></a></li>
<li><a href="#"><img src="img/banner.png" alt="バナー画像" class="banner"></a></li>
</ul>
</div>
<div class="news">
<h2 class="h2">新着情報</h2>
<ul role="list">
<li>20XX.XX.XX 〜なニュースがありました</li>
<li>20XX.XX.XX 〜なニュースがありました</li>
<li>20XX.XX.XX 〜なニュースがありました</li>
</ul>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<div class="footer-content">
<a href="index.html" class="logo">Sample</a>
<div class="copyright">Copyright © SAMPLE</div>
</div>
</div>
</footer>
</body>
</html>
×ボタンのデザインはCSSで実装するため、CSSを以下のように修正します。
@media screen and (max-width: 768px) {
.content .container {
flex-direction: column;
gap: 0;
margin: 10px auto 20px;
}
.sidebar {
order: 2;
}
.banner {
width: 100%;
}
.news {
order: 1;
}
.header-top {
flex-direction: column;
align-items: normal;
position: relative;
}
.toggle-btn-open {
display: block;
cursor: pointer;
max-width: 35px;
width: 100%;
position: absolute;
top: 5px;
right: 15px;
}
.toggle-btn-open span {
display: block;
width: 100%;
height: 5px;
background-color: #333;
margin: 5px 0;
}
/* ここから */
.toggle-btn-close {
position: fixed;
z-index: 9999;
top: 15px;
right: 15px;
cursor: pointer;
width: 30px;
height: 30px;
opacity: 0;
}
.toggle-btn-close::before, .toggle-btn-close::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 5px;
height: 30px;
background: #C9C9C9;
}
.toggle-btn-close::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.toggle-btn-close::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
/* ここまで追加 */
.tel {
margin: 10px auto 0;
}
.nav {
position: fixed;
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
top:0;
right: -120%;
width: 100%;
height: 100vh;
background:#000;
}
.nav-list {
flex-direction: column;
}
.nav-item a {
color: #fff;
}
.footer {
padding: 25px 0 30px;
}
.footer .logo {
margin-bottom: 10px;
}
}
続いて、JavaScriptのコードの実装をしていきます。先述の通り、JavaScriptのコードはindex.jsに書いていきます。
実装する処理の詳細なイメージとしては、
- ボタンをクリックする
- グローバルナビゲーションのclass属性に
activeという名前のCSSのclassを付与(=グローバルナビゲーションを表示) - グローバルナビゲーションの閉じる(×)ボタンをクリック
- グローバルナビゲーションのclass属性から
activeのclassを削除(=グローバルナビゲーションを非表示にする)
以上になります。
まずはJavaScriptを実装しましょう。index.jsに以下のコードを記載します。
onClickToggle = () => {
const toggleBtnClose = document.querySelector(".toggle-btn-close");
const nav = document.querySelector(".nav");
toggleBtnClose.classList.toggle("active");
nav.classList.toggle("active");
}
データや値を格納するための名前のことを変数といいます。JavaScriptでは、const 変数名 = 値という形で、特定の値や要素に名前をつけて扱いやすくすることができます。
難しく感じるかもしれませんが、まずは「特定の値や要素に名前をつけられる」と覚えておけばOKです。
1行目では、HTMLファイル内のクラス名が.toggle-btn-closeの要素を取得し、それにtoggleBtnCloseという変数名をつけています。これはスマホ画面でハンバーガーアイコンを押したときに表示されるグローバルナビを「閉じるためのボタン」です。
2行目では、クラス名が.navの要素(グローバルナビ)を取得して、navという変数名をつけています。
そして3、4行目では、toggleBtnCloseとnavの両方にactiveクラスを「トグル(切り替え)」します。つまり、activeクラスが付いていなければ付け、付いていれば外します。
activeクラスが付いていると、グローバルナビと閉じるボタンは表示され、付いていないと非表示になります。
この関数を、htmlのtoggle-btn-open、toggle-btn-closeのclass名が付与されたボタンに付与します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>サンプルサイト</title>
<link rel="stylesheet" media="all" href="css/style.css" />
<link rel="stylesheet" media="all" href="css/reset.css" />
<script src="./js/index.js"></script>
</head>
<body>
<header class="header">
<div class="container">
<div class="header-top">
<h1 class="logo"><a href="index.html">Sample</a></h1>
<label for="toggle" class="toggle-btn-open" onclick="onClickToggle()"> <!-- ここを変更 -->
<span></span>
<span></span>
<span></span>
</label>
<div class="toggle-btn-close" onclick="onClickToggle()"></div> <!-- ここを変更 -->
<div class="tel">TEL:00-0000-0000</div>
</div>
<div class="nav">
<ul class="nav-list" role="list">
<li class="nav-item"><a href="#">ホーム</a></li>
<li class="nav-item"><a href="#">会社概要</a></li>
<li class="nav-item"><a href="#">事業内容</a></li>
<li class="nav-item"><a href="#">採用情報</a></li>
<li class="nav-item"><a href="#">お問い合わせ</a></li>
</ul>
</div>
</div>
</header>
<div>
<img src="img/mainimg.png" alt="メイン画像" class="main-img">
</div>
<div class="content">
<div class="container">
<div class="sidebar">
<ul role="list">
<li><a href="#"><img src="img/banner.png" alt="バナー画像" class="banner"></a></li>
<li><a href="#"><img src="img/banner.png" alt="バナー画像" class="banner"></a></li>
<li><a href="#"><img src="img/banner.png" alt="バナー画像" class="banner"></a></li>
</ul>
</div>
<div class="news">
<h2 class="h2">新着情報</h2>
<ul role="list">
<li>20XX.XX.XX 〜なニュースがありました</li>
<li>20XX.XX.XX 〜なニュースがありました</li>
<li>20XX.XX.XX 〜なニュースがありました</li>
</ul>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<div class="footer-content">
<a href="index.html" class="logo">Sample</a>
<div class="copyright">Copyright © SAMPLE</div>
</div>
</div>
</footer>
</body>
</html>
以上の実装により、ボタンをクリックするとグローバルナビゲーションのclass属性にactiveのclassを付与することが可能になりました。
では次は、CSSにアニメーションの処理を実装していきます。
アニメーション
実装するアニメーションは以下のようになります。
-
画面幅768px以下(スマホや小さい画面)で、ナビゲーションメニュー(.nav)は最初は画面の右外(画面外)に隠しておく。
-
画面右上にあるハンバーガーメニュー(.toggle-btn-open)を押すと、ナビゲーションメニューが右から画面内にスライドして表示される。
-
ナビゲーションメニューが表示された状態では×ボタン(.toggle-btn-close)が表示され、このボタンを押すとメニューが右に閉じて元の状態に戻る。
CSSの実装は以下になります。
@media screen and (max-width: 768px) {
.content .container {
flex-direction: column;
gap: 0;
margin: 10px auto 20px;
}
.sidebar {
order: 2;
}
.banner {
width: 100%;
}
.news {
order: 1;
}
.header-top {
flex-direction: column;
align-items: normal;
position: relative;
}
.toggle-btn-open {
display: block;
cursor: pointer;
max-width: 35px;
width: 100%;
position: absolute;
top: 5px;
right: 15px;
}
.toggle-btn-open span {
display: block;
width: 100%;
height: 5px;
background-color: #333;
margin: 5px 0;
}
/* fadeInDelayの処理を追加 */
@keyframes fadeInDelay {
0% { opacity: 0; }
100% { opacity: 1; }
}
.toggle-btn-close {
position: fixed;
z-index: 9999;
top: 15px;
right: 15px;
cursor: pointer;
width: 30px;
height: 30px;
opacity: 0;
animation: fadeInDelay 1s ease 0.6s forwards; /* toggle-btn-closeのanimationにfadeInDelayを付与 */
}
.toggle-btn-close::before, .toggle-btn-close::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 5px;
height: 30px;
background: #C9C9C9;
}
.toggle-btn-close::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.toggle-btn-close::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
/* toggle-btn-close.activeの処理を追加 */
.toggle-btn-close.active {
display: block;
}
.tel {
margin: 10px auto 0;
}
.nav {
position: fixed;
display: flex;
align-items: center;
justify-content: center;
z-index: 999;
top:0;
right: -120%;
width: 100%;
height: 100vh;
background:#000;
transition: all 0.6s; /* この行を追加 */
}
/* nav.activeの処理を追加 */
.nav.active {
right: 0;
}
.nav-list {
flex-direction: column;
}
.nav-item a {
color: #fff;
}
.footer {
padding: 25px 0 30px;
}
.footer .logo {
margin-bottom: 10px;
}
}
グローバルナビ(.nav)は、right: 120%を指定されているため、画面幅768px以下(スマホや小さい画面)の初期表示時、画面の右外(画面外)に隠れています。
画面右上にあるハンバーガーメニュー(.toggle-btn-open)を押すことで、グローバルナビに.activeクラスが付与されてright: 0となり、右側からグローバルナビが出現します。
しかしこれだけでは、グローバルナビゲーションが瞬間的に画面に出現してしまうため、スライドして表示させることはできません。そこで、.navにtransition: all 0.6sを付与することで、この位置変更が0.6秒かけてスムーズに動く(アニメーションする)スライドイン・アウトの効果を生み出します。
メニューが表示された状態では、.activeクラスが付与されることで×ボタン(.toggle-btn-close)が表示されます。
×ボタンには、animationプロパティでfadeInDelayという値が設定されています。
fadeInDelayの内容は、「透明度(opacity)が0から1へ徐々に変わる」ことを示しています。
0%(アニメーション開始時点)で透明(opacity: 0)、100%(アニメーション終了時点)で完全に見える(opacity: 1)状態になります。
×ボタンのanimationはfadeInDelay 1s ease 0.6s forwards;となっています。これはアニメーション開始まで0.6秒待ち、その後1秒かけてバツボタンを透明な状態から見える状態(opacityを0から1)へ切り替えることを意味します。
×ボタンは押すと、今度はメニューが右へ閉じて元の状態に戻ります。
index.htmlを開き、サイトの表示をスマホ表示に切り替えます。(詳しい手順は、こちらの記事を参照ください。)
ハンバーガーアイコンをクリックし、グローバルメニューが表示されれば成功です。






