個人サイト制作:サイトマップへ戻る

レスポンシブデザインに対応したハンバーガーメニュー

スマートフォンやタブレットが当たり前になった今、レスポンシブデザインにおけるハンバーガーメニューは単なる装飾ではなく、ユーザー体験を支える重要な仕組みになっています。
限られた画面スペースの中で、情報を整理しつつ直感的に操作できる導線を提供することは、サイトの信頼性にも直結します。
小さなアイコンをタップするだけでナビゲーションが展開する仕組みは、ユーザーに「迷わず使える」という安心感を与え、同時にデザインの余白やコンテンツの見やすさを確保する役割も果たします。
つまりハンバーガーメニューは、レスポンシブデザインの中で「見せたいもの」と「隠すべきもの」のバランスを取るための象徴的な存在かと思うんですよね。

あ、そうそう…
通りが良いからハンバーガーメニューと言っちゃってるけど、正しくは「ナビゲーションドロワーアイコン」とか「メニューアイコン」と呼びます。

摺りガラス効果を施したハンバーガーメニュー

上述通り、とっても大切な機能です。
しかしタップされた瞬間に画面を占有してしまうから、なかなかデザインが難しい側面があるんですよね。
いろんなやり方があると思う。
ここでは摺りガラス効果を取り入れたCSSのパターンをご紹介します。


.fden-hamburger-menu {
 position: relative;
}

.fden-hamburger-button {
 font-size: 16px;
 cursor: pointer;
 color: #1A73E8;
 background: linear-gradient(to bottom, rgba(173, 216, 230, 0.5), rgba(173, 216, 230, 0));
 border: none;
 padding: 10px;
 border-radius: 5px;
 font-weight: bold;
 letter-spacing: 0.3px;
 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
 transition: background 0.3s ease-in-out, color 0.3s ease-in-out;
}

.fden-hamburger-button:hover {
 background: linear-gradient(to bottom, rgba(173, 216, 230, 0.2), rgba(173, 216, 230, 0));
}

.fden-menu {
 display: none;
 position: absolute;
 top: 40px;
 left: 0;
 background: rgba(255, 255, 255, 0.1);
 backdrop-filter: blur(6px);
 -webkit-backdrop-filter: blur(6px);
 border: 1px solid rgba(255, 255, 255, 0.2);
 box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
 z-index: 1000;
 opacity: 0;
 transition: opacity 0.5s ease, transform 0.5s ease;
 transform: translateY(-10px);
 border-radius: 18px;
}

.fden-menu.show {
 display: block;
 opacity: 1;
 transform: translateY(0);
}

.fden-menu a {
 display: block;
 padding: 15px;
 text-decoration: none;
 font-weight: bold;
 letter-spacing: 0.3px;
 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
 color: #1A73E8;
 transition: color 0.3s ease-in-out;
}

.fden-menu a:hover,
.fden-submenu a:hover,
.fden-menu .fden-submenu-toggle1:hover,
.fden-menu .fden-submenu-toggle2:hover {
 color: #0A1F44;
}

.fden-submenu {
 display: none;
 padding-left: 20px;
 opacity: 0;
 transition: opacity 0.5s ease, transform 0.5s ease;
 transform: translateY(-10px);
}

.fden-submenu.show {
 display: block;
 opacity: 1;
 transform: translateY(0);
}

.fden-menu .fden-submenu-toggle1 {
 font-weight: bold;
 letter-spacing: 0.3px;
 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
 color: #1A73E8;
 cursor: pointer;
}

.fden-menu .fden-submenu-toggle2 {
 font-weight: bold;
 letter-spacing: 0.3px;
 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
 color: #0078D4;
 cursor: pointer;
}

.fden-submenu#fden-submenu1 a {
 font-weight: bold;
 letter-spacing: 0.3px;
 text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
 color: #0078D4;
 transition: color 0.3s ease-in-out;
}

.fden-submenu#fden-submenu1 a:hover {
 color: #0A1F44;
}

@media (max-width: 768px) {
 .fden-hamburger-button {
  font-size: 14px;
  padding: 8px;
 }

 .fden-menu a {
  padding: 10px;
 }
}
    

クラスセレクター .fden-hamburger-menu

position: relative;
親要素を「基準」として扱います。中の子要素(例えばメニュー)を position: absolute; で配置するとき、この親が基準点になります。

クラスセレクター .fden-hamburger-button

font-size: 16px;
文字の大きさを 16px にします。
cursor: pointer;
ホバーするとカーソルが手の形になり、クリックできる感じを出します。
color: #1A73E8;
文字色を Google系の青にします。
background: linear-gradient(to bottom, rgba(173, 216, 230, 0.5), rgba(173, 216, 230, 0));
上から下へのグラデーション背景。上側は薄い水色の半透明、下に行くほど透明になります。
border: none;
ボタンの枠線を消します。
padding: 10px;
内側の余白を 10px にして、クリックしやすく見やすくします。
border-radius: 5px;
角を 5px 丸めて、柔らかい印象にします。
font-weight: bold;
文字を太字にします。
letter-spacing: 0.3px;
文字の間隔をほんの少し広げて、視認性を上げます。
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
黒の半透明で軽い影を付け、立体感を出します。
transition: background 0.3s ease-in-out, color 0.3s ease-in-out;
背景と文字色の変化を 0.3 秒で滑らかにします(ホバー時のアニメに効く)。

クラスセレクター .fden-hamburger-button:hover

background: linear-gradient(to bottom, rgba(173, 216, 230, 0.2), rgba(173, 216, 230, 0));
ホバー時は背景の水色の濃さを少し弱くし、反応を感じさせます。

クラスセレクター .fden-menu

display: none;
初期状態ではメニューを非表示にします。
position: absolute;
親(relative の要素)を基準に、自由配置にします。
top: 40px;
基準点から下へ 40px の位置に表示します。
left: 0;
左端に揃えます。
background: rgba(255, 255, 255, 0.1);
ごく薄い白の半透明背景。後ろが少し透けます。
backdrop-filter: blur(6px);
背景(背後のコンテンツ)を 6px ぼかすガラス風効果。
-webkit-backdrop-filter: blur(6px);
Safari など一部ブラウザ用の互換指定です。
border: 1px solid rgba(255, 255, 255, 0.2);
薄い白の枠線で輪郭を作ります。
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
ふわっと浮く影を付けます(下方向に 2px、ぼかし 10px)。
z-index: 1000;
重なり順を高くして、他の要素より前面に出します。
opacity: 0;
透明(見えない)にして、後でアニメ付きで表示させる準備。
transition: opacity 0.5s ease, transform 0.5s ease;
透明度と位置変化を 0.5 秒で滑らかにします。
transform: translateY(-10px);
初期状態は少し上にずらしておき、表示時に下へスッと出す演出。
border-radius: 18px;
角をしっかり丸めてカード風の見た目にします。

クラスセレクター .fden-menu.show

display: block;
非表示から表示へ切り替えます。
opacity: 1;
不透明にします(フェードイン)。
transform: translateY(0);
上にずらしていた位置を元に戻し、スライドイン完成。

クラスセレクター .fden-menu a

display: block;
リンクをブロック要素にして、行全体をクリック可能にします。
padding: 15px;
余白を広めに取り、押しやすく読みやすくします。
text-decoration: none;
下線を消します。
font-weight: bold;
太字で項目を強調します。
letter-spacing: 0.3px;
文字間を少し広げます。
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
軽い影で可読性と立体感を付けます。
color: #1A73E8;
項目の文字色を青にします。
transition: color 0.3s ease-in-out;
文字色の変化を滑らかにします(ホバー時など)。
ホバー時の色変化
.fden-menu a:hover, .fden-submenu a:hover,
.fden-menu .fden-submenu-toggle1:hover,
.fden-menu .fden-submenu-toggle2:hover { color: #0A1F44; }
メニュー内のリンクやサブメニューのリンク、トグル部分をホバーしたら濃紺色に変え、反応を明確にします。

クラスセレクター .fden-submenu

display: none;
サブメニューは初期状態では非表示。
padding-left: 20px;
左に 20px のインデントを付け、階層を視覚化します。
opacity: 0;
透明にして、後でアニメ表示する準備。
transition: opacity 0.5s ease, transform 0.5s ease;
フェードと位置のアニメを 0.5 秒で滑らかに。
transform: translateY(-10px);
少し上から表示開始して、スッと現れる演出。

クラスセレクター .fden-submenu.show

display: block;
表示に切り替えます。
opacity: 1;
不透明にしてフェードイン。
transform: translateY(0);
位置を元に戻してスライドイン。
トグル要素(サブメニュー開閉用)の見た目
.fden-menu .fden-submenu-toggle1 {
font-weight: bold;
letter-spacing: 0.3px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
color: #1A73E8;
cursor: pointer;
}
トグル1は青(Google系)で、太字・わずかな文字間・軽い影。クリックできるようポインター表示。
.fden-menu .fden-submenu-toggle2 {
font-weight: bold;
letter-spacing: 0.3px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
color: #0078D4;
cursor: pointer;
}
トグル2は別の青(Microsoft系)。同じく太字・影・ポインターで、役割の違いを色で示します。

クラスセレクター .fden-submenu#fden-submenu1 a

font-weight: bold;
サブメニュー1内のリンクを太字に。
letter-spacing: 0.3px;
文字間を少し広げます。
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
軽い影で読みやすく。
color: #0078D4;
Microsoft系の青で差別化します。
transition: color 0.3s ease-in-out;
色の変化を滑らかに。

クラスセレクター .fden-submenu#fden-submenu1 a:hover

color: #0A1F44;
ホバーで濃紺に変更し、反応を示します。
メディアクエリ(スマホなど幅768px以下)
@media (max-width: 768px) { ... }
画面幅が 768px 以下のときだけ、次の内側のルールを適用します。

内側のルール

.fden-hamburger-button { font-size: 14px; padding: 8px; }
ボタンの文字と余白を少し小さくし、モバイルでの収まりを良くします。
.fden-menu a { padding: 10px; }
メニュー項目の余白をややコンパクトにして、縦の詰まりを最適化します。

こういうCSSの使い方のポイントとしては、次のようなものが挙げられるかと。

表示切替の仕組み:
.show クラスの付け外しで「非表示→表示」とアニメ(フェード+スライド)を制御しています。 JavaScriptでボタンをクリックしたら .fden-menu.fden-submenu.show を付けるのが基本です。
ガラス風の演出:
background の半透明+backdrop-filter のぼかしで、モダンな「ガラスモーフィズム」風を実現しています。 対応しないブラウザではぼかしが出ない場合もあるため、見た目の劣化が許容されるデザインにしてあります。
色のロジック:
メイン操作は Google系ブルー(#1A73E8)、階層や役割の差別化に Microsoftブルー(#0078D4)を組み合わせ、 ホバーは濃紺(#0A1F44)で一体感を持たせています。

このCSSはちょっと複雑かも…要するに

あるいは、細かいプロパティを一つずつ追うよりも、まずは「全体の役割」をイメージする方が理解しやすいのかもしれません。
私がこのコードを書いたのは学生時代で、当時はワケ分からなかったですよ…
最近になって、当サイトに取り入れるために倉庫から引っ張り出していろいろ手を加えたものです。

んーとね…ちょっと文章で表現してみましょうか!
ここで使われているのは「ハンバーガーメニュー」と呼ばれる仕組みで、スマホや小さな画面でよく見かける折りたたみ式のメニューをスタイリッシュに動かすためのスタイルです。
青を基調にしたボタンをクリックすると、メニューがふわっと下に現れる──そんなアニメーションが仕込まれています。
背景は半透明でぼかしがかかり、まるでガラス越しに見ているような質感を演出。
さらに中にはサブメニューがあり、必要なときだけスライドして展開される仕組みなのです。
リンクにカーソルを合わせると文字色が濃く変わり、ユーザーは「今ここに触れている」と直感的に感じられるようになっています。
そして画面が狭くなると文字サイズや余白が自動で調整され、スマホでも快適に閲覧できるよう工夫されています。
要するに、このCSSは「ボタンを押すとガラス風のメニューがアニメーションで開き、階層的なサブメニューも展開できる」という体験を作り出すためのものなのです。

ハンバーガーメニューの概要

フェードアウト効果の草花写真

まずは全体的なコード同士の関わりについて説明が必要です。
全てのページに「メニューを開く」をいうボタンがありますよね?
その部分はハンバーガーメニューを差し込むhtmlコードです。
それをタップするとJavaScriptが動作します。
結果として何が起きるかというと、別に用意してある menu.html というメニューの中身を記述しているhtmlが、ハンバーガーメニューの入口である「メニューを開く」というボタンに差し込まれるわけです。
そして準備してあるCSSがデザインを担当しています。

まずはハンバーガーメニューを差し込むhtmlコードから。
これは全てのページに設置する必要があります。


<div class="fden-hamburger-menu">
   <button class="fden-hamburger-button" id="fden-hamburger-button" onclick="toggleMenu()">☰ メニューを開く
    ▼</button>
   <div class="fden-menu" id="fden-menu">
    <div id="fden-menu-content"></div>
   </div>
  </div>
  <script src="../script/menu.js"></script>
    

htmlコードそのものはそんなに複雑ではありません。
ていうかなるべくシンプルに書くようにしているんだけどね。
次は、ハンバーガーメニューの中身が記述されているhtmlファイルです。


<!DOCTYPE html>
<html lang="ja">

<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>fein's appのハンバーガーメニュー</title>
</head>

<body>
 <a href="/another-eden/anaden_sitemap.html">アナザーエデン関連ページ・サイトマップ</a>
 <a href="/contents/site_create.html">個人サイト制作関連ページ・サイトマップ</a>
 <a href="/fish/fish_sitemap.html">アウトドア関連ページ・サイトマップ</a>
 <a href="/contents/rss.html">更新のお知らせ</a>
 <a href="/fish/blog.html" style="text-decoration:none;">
  fein's blog
  <img src="/menu/mspass.webp" alt="このサイトのシンボルマーク" style="width:40px; vertical-align:middle; margin-left:5px;"></a>
 <a href="/menu/symbol.html#feininfo">サイト制作者について</a>
 <a href="/contents/policy.html">サイトのポリシーや仕様</a>
 <div id="denmenu">
  <a href="#" class="fden-submenu-toggle1" id="toggle-site-content"
   onclick="toggleSubMenu('fden-submenu2', 'toggle-site-content', event)">アクセスランキングTop10▼</a>

  <div class="fden-submenu" id="fden-submenu2">
   <a href="/another-eden/atelier_studio.html">Ⅰ.ファンサイト制作のためのアトリエ</a>
   <a href="/another-eden/anaden_fansite.html">Ⅱ.アナザーエデンのファンサイト&ブログ等を作ってみたい方へ</a>
   <a href="/another-eden/anaden_beginner.html">Ⅲ.アナザーエデンの初心者向けガイド</a>
   <a href="/another-eden/anaden_feinpdf_teyul_menas.html">Ⅳ.グラスタ表を生んだテユールメナス</a>
   <a href="/another-eden/lua.html">Ⅴ.アナザーエデンのプログラミングを個人サイトで試す</a>
   <a href="/contents/aipay.html">Ⅵ.アクセス課金とWebの設計 ~ AIクローラー課金モデル ~</a>
   <a href="/contents/onedrive.html">Ⅶ.OneDriveの基本と落とし穴|Windows 11での設定・ファイル管理の注意点</a>
   <a href="/contents/album_script.html">Ⅷ.JavaScriptでイラストアルバムを作成する</a>
   <a href="/top">Ⅸ.個人サイトへPythonのFlaskを導入する</a>
   <a href="/contents/domain.html">Ⅹ.注意したい独自ドメイン設定手順とルール</a>
  </div>

  <a href="#" class="fden-submenu-toggle2" id="toggle-popular-pages"
   onclick="toggleSubMenu('fden-submenu1', 'toggle-popular-pages', event)">制作者からのお便り▼</a>
  <div class="fden-submenu" id="fden-submenu1">
   <a href="/contents/pwa.html#Progressive_Web_Application">このサイトがアプリになりました!</a>
   <a href="/contents/x_exoduslink.html">個人サイトのリンク掲載をご希望の方へ</a>
   <a href="/contents/form.html">お問い合わせはこちら</a>
   <a href="https://bsky.app/profile/feinatelier.org">Bluesky:公式SNS</a>
   <a href="https://github.com/fein-denscothmn">GitHub:ソースコード</a>
   <a href="https://portal.feinatelier.org/" style="display: flex; align-items: center; text-decoration: none;">
    <img src="/image/anafish.webp" alt="アナザーエデンのバディ_ピスケ" style="width: 6%; height: auto; margin-right: 10px;">
    fein's portal:ポータルサイト
   </a>
   <a href="/fish/instagram.html">※maintenance[アプリ制作者用スペース]</a>
   <a href="/another-eden/grasta.html">Fein Atelier - org</a>
  </div>

</body>

</html>
    

単なるリンクのリストですよ。
コードもいたってシンプル。
これがJavaScriptによって全てのページに差し込まれ、CSSによってデザインされる。
そうするとハンバーガーメニューになるわけです。

では、CSSの説明に移ります。

メニューを作るCSS

細々したデザインはそうでもないんだけど、ここの特徴はアニメーション設定になるでしょうか。
閲覧者が頻繁にタップするポイントなので、カクカクした動きにならないようにしています。

※ここにあるコードは一昔前のやつです。最新版はこのページの上にあるコードですよ。
大差ないんだけどね。気になる方はファンサイト制作のためのアトリエからジャンプできるコードが最新版です。

ハンバーガーメニューを作るmenu.css


/* ハンバーガーメニューのコンテナスタイル */
.fden-hamburger-menu {
    position: relative; /* 相対位置を指定 */
}

/* ハンバーガーボタンのスタイル */
.fden-hamburger-button {
    font-size: 16px; /* フォントサイズを設定 */
    cursor: pointer; /* カーソルをポインターに変更 */
    color: #1A73E8; /* ボタンの文字色を設定 (Google blue) */
    background: linear-gradient(to bottom, rgba(173, 216, 230, 0.5), rgba(173, 216, 230, 0)); /* 背景のグラデーションを追加 */
    border: none; /* ボーダーをなしにする */
    padding: 10px; /* 内側の余白を設定 */
    border-radius: 5px; /* 四隅を丸める */
    font-weight: bold; /* 文字を太字にする */
    transition: background 0.3s ease-in-out, color 0.3s ease-in-out; /* 背景色と文字色の変化にアニメーションを追加 */
}

/* ハンバーガーボタンをホバーしたときのスタイル */
.fden-hamburger-button:hover {
    background: linear-gradient(to bottom, rgba(173, 216, 230, 0.2), rgba(173, 216, 230, 0)); /* 背景のグラデーションを変更 */
}

/* メニューのスタイル */
.fden-menu {
    display: none; /* 初期状態で非表示 */
    position: absolute; /* 絶対位置を指定 */
    top: 40px; /* 上から40pxの位置に配置 */
    left: 0; /* 左端に配置 */
    background-color: white; /* 背景色を白に設定 */
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); /* 影を追加 */
    z-index: 1000; /* 重なり順を設定 */
    opacity: 0; /* 初期状態で透明 */
    transition: opacity 0.5s ease, transform 0.5s ease; /* 透明度と変形にアニメーションを追加 */
    transform: translateY(-10px); /* 初期状態で少し上に移動 */
}

/* メニューが表示されたときのスタイル */
.fden-menu.show {
    display: block; /* 表示 */
    opacity: 1; /* 不透明に設定 */
    transform: translateY(0); /* 元の位置に移動 */
}

/* メニュー内のリンクのスタイル */
.fden-menu a {
    display: block; /* ブロック要素として表示 */
    padding: 15px; /* 内側の余白を設定 */
    text-decoration: none; /* 下線をなしにする */
    color: black; /* 文字色を黒に設定 */
    transition: background 0.3s ease-in-out; /* 背景色の変化にアニメーションを追加 */
}

/* メニュー内のリンクをホバーしたときのスタイル */
.fden-menu a:hover {
    background-color: #e0e0e0; /* 背景色を変更 */
}

/* サブメニューのスタイル */
.fden-submenu {
    display: none; /* 初期状態で非表示 */
    padding-left: 20px; /* 左に余白を設定 */
    opacity: 0; /* 初期状態で透明 */
    transition: opacity 0.5s ease, transform 0.5s ease; /* 透明度と変形にアニメーションを追加 */
    transform: translateY(-10px); /* 初期状態で少し上に移動 */
}

/* サブメニューが表示されたときのスタイル */
.fden-submenu.show {
    display: block; /* 表示 */
    opacity: 1; /* 不透明に設定 */
    transform: translateY(0); /* 元の位置に移動 */
}

/* サブメニューのトグルボタン1のスタイル */
.fden-menu .fden-submenu-toggle1 {
    font-weight: bold; /* 文字を太字にする */
    color: #1A73E8; /* 文字色を設定 (Google blue) */
    cursor: pointer; /* カーソルをポインターに変更 */
}

/* サブメニューのトグルボタン2のスタイル */
.fden-menu .fden-submenu-toggle2 {
    font-weight: bold; /* 文字を太字にする */
    color: #0078D4; /* 文字色を設定 (Microsoft blue) */
    cursor: pointer; /* カーソルをポインターに変更 */
}

/* ビューポートの幅が768px以下の場合のスタイル */
@media (max-width: 768px) {
    .fden-hamburger-button {
        font-size: 14px; /* フォントサイズを14pxに設定 */
        padding: 8px; /* 内側の余白を縮小 */
    }

    .fden-menu a {
        padding: 10px; /* 内側の余白を縮小 */
    }
}
    

このコードにはいくつかのアニメーションが含まれていますが、主にtransitionプロパティを使用しています。

メニューのアニメーション設定

ここはちょっと細かく分かれているんですよね。
重要なポイントでありながら、あまり大仰なアニメーションは付けたくないです。
今のところ、次のような設定で落ち着いています。

ハンバーガーボタンのアニメーション

transition: background 0.3s ease-in-out, color 0.3s ease-in-out; /* 背景色と文字色の変化にアニメーションを追加 */

背景色と文字色のアニメーション
このtransitionプロパティ:背景色と文字色が変化する際にアニメーションを追加します。
0.3sはアニメーションの持続時間:変化が0.3秒で完了することを示しています。
ease-in-outはイージング関数:アニメーションの始まりと終わりがスムーズになる効果があります。
メニューの表示・非表示のアニメーション

初期状態


opacity: 0; /* 初期状態で透明 */
transition: opacity 0.5s ease, transform 0.5s ease; /* 透明度と変形にアニメーションを追加 */
transform: translateY(-10px); /* 初期状態で少し上に移動 */

透明度と変形のアニメーション
opacity: 0;:メニューが初期状態で透明であることを示しています。
transition: opacity 0.5s ease, transform 0.5s ease;:透明度と位置の変化に0.5秒のアニメーションを追加します。
transform: translateY(-10px);:メニューが初期状態で少し上に移動していることを示しています。

表示状態


.fden-menu.show {
    display: block; /* 表示 */
    opacity: 1; /* 不透明に設定 */
    transform: translateY(0); /* 元の位置に移動 */
}

表示時のアニメーション
opacity: 1;:メニューが完全に表示されることを示しています。
transform: translateY(0);:メニューが元の位置に移動していることを示しています。
transitionプロパティ:これらの変化がスムーズにアニメーションされます。
メニュー内のリンクのアニメーション

transition: background 0.3s ease-in-out; /* 背景色の変化にアニメーションを追加 */

背景色のアニメーション
transition: background 0.3s ease-in-out;:リンクの背景色が変化する際にアニメーションを追加します。
0.3sはアニメーションの持続時間:変化が0.3秒で完了することを示しています。
ease-in-outはイージング関数:アニメーションの始まりと終わりがスムーズになる効果があります。
サブメニューのアニメーション

初期状態


opacity: 0; /* 初期状態で透明 */
transition: opacity 0.5s ease, transform 0.5s ease; /* 透明度と変形にアニメーションを追加 */
transform: translateY(-10px); /* 初期状態で少し上に移動 */

透明度と変形のアニメーション
opacity: 0;:サブメニューが初期状態で透明であることを示しています。
transition: opacity 0.5s ease, transform 0.5s ease;:透明度と位置の変化に0.5秒のアニメーションを追加します。
transform: translateY(-10px);:サブメニューが初期状態で少し上に移動していることを示しています。

表示状態


.fden-submenu.show {
    display: block; /* 表示 */
    opacity: 1; /* 不透明に設定 */
    transform: translateY(0); /* 元の位置に移動 */
}

表示時のアニメーション
opacity: 1;:サブメニューが完全に表示されることを示しています。
transform: translateY(0);:サブメニューが元の位置に移動していることを示しています。
transitionプロパティ:これらの変化がスムーズにアニメーションされます。

全体的に、もう少し遅いほうが良いのかもしれない。
あと、このハンバーガーメニューはワンタッチで移動できるサブメニューのような役割を果たしています。
ページ移動のメインになるのはグローバルナビゲーションとサイトマップ。
だからあまり多くのリンクを設定しないようにしていますね。

メニューを作るJavaScript

フェードアウト効果の草花写真

上述したけども、個人でサイトを作ろうとしたときに必ずと言って良いほど話題になるのが、このサイトにもある「メニュー」です。
CSSだけで組むこともできますが、素直にJavaScriptを交えたほうがラクかと思いますね。
このサイトではグローバルナビゲーションをメインとして、このハンバーガーメニューはサブメニューとして活躍してもらってます。


function toggleMenu() {
 var menu = document.getElementById('fden-menu');
 var button = document.getElementById('fden-hamburger-button');
 if (menu.classList.contains('show')) {
  menu.classList.remove('show');
  button.innerHTML = '☰ メニューを開く ▼';
  setTimeout(function () {
   menu.style.display = 'none';
  }, 300);
 } else {
  menu.style.display = 'block';
  button.innerHTML = '× メニューを閉じる ▲';
  setTimeout(function () {
   menu.classList.add('show');
  }, 10);
 }
}

function toggleSubMenu(id, buttonId) {
 var submenu = document.getElementById(id);
 var button = document.getElementById(buttonId);
 if (submenu.classList.contains('show')) {
  submenu.classList.remove('show');
  button.innerHTML = button.innerHTML.replace('▲', '▼');
  setTimeout(function () {
   submenu.style.display = 'none';
  }, 300);
 } else {
  submenu.style.display = 'block';
  button.innerHTML = button.innerHTML.replace('▼', '▲');
  setTimeout(function () {
   submenu.classList.add('show');
  }, 10);
 }
}

document.addEventListener('DOMContentLoaded', function () {
 fetch('../menu/menu.html')
  .then(response => response.text())
  .then(data => {
   document.getElementById('fden-menu-content').innerHTML = data;
  });

 document.addEventListener('click', function (event) {
  var menu = document.getElementById('fden-menu');
  var button = document.getElementById('fden-hamburger-button');
  var isClickInside = menu.contains(event.target) || button.contains(event.target);
  if (!isClickInside && menu.classList.contains('show')) {
   menu.classList.remove('show');
   button.innerHTML = '☰ メニューを開く ▼';
   setTimeout(function () {
    menu.style.display = 'none';
   }, 300);
  }
 });
});
    

全てのページのメニューを手作りするの?!

フェードアウト効果の草花写真

さっきも似たようなこと書いたけど。
いやいや…現実味がないと思いますよ?
全てのページで内容を統一しなければいけないのに。
一応Visual Studio Codeは複数ファイルの一括置換ができますが、あまり長いコードを多数のファイルで置換させていると、あるいはどこかでミスが出ていても気付けない可能性があります。
私はグローバルナビゲーションでしか一括置換はやっていないですね。
SEOの観点からもhtmlコードの直接記述であることが望ましいからです。
しかし、閲覧者の利便性を確保するのがハンバーガーメニューの目的なのですから、ここは何かしらの方法でスクリプトによる自動生成をしたほうが良いでしょう。

メニューのJavaScript概要

では、このスクリプトについて詳細な説明を行います。

メニューを開閉する機能

ボタンをクリックすると、メニューが開いたり閉じたりします。
メニューが表示されている場合は、'show' クラスを削除し、300ミリ秒後にメニューを非表示にします。
メニューが非表示の場合は、メニューを表示し、'show' クラスを追加します。ボタンのテキストも適宜変更されます。

サブメニューを開閉する機能

サブメニューの開閉もメインメニューと同様に動作します。
指定されたIDのサブメニューが表示されている場合は、'show' クラスを削除し、300ミリ秒後に非表示にします。
非表示の場合は、サブメニューを表示し、'show' クラスを追加します。ボタンのテキストも適宜変更されます。

ページの読み込み完了後の処理

ページが完全に読み込まれた後、指定されたURLからメニューのHTMLファイルを取得し、その内容をメニューコンテンツに挿入します。

クリックイベントの処理

ページ内でクリックが発生すると、そのクリックがメニューやボタンの内部で発生したかどうかをチェックします。
もしメニューやボタンの外部でクリックが発生し、メニューが表示されている場合は、メニューを閉じます。

toggleMenu関数

function toggleMenu() {
 var menu = document.getElementById('fden-menu');
 var button = document.getElementById('fden-hamburger-button');
 if (menu.classList.contains('show')) {
  menu.classList.remove('show');
  button.innerHTML = '☰ メニューを開く ▼';
  setTimeout(function () {
   menu.style.display = 'none';
  }, 300);
 } else {
  menu.style.display = 'block';
  button.innerHTML = '× メニューを閉じる ▲';
  setTimeout(function () {
   menu.classList.add('show');
  }, 10);
 }
}

1. メニューとボタンの取得


var menu = document.getElementById('fden-menu');
var button = document.getElementById('fden-hamburger-button');
   

menu にはIDが 'fden-menu' の要素を取得します。
button にはIDが 'fden-hamburger-button' の要素を取得します。

2. メニューの表示/非表示を切り替え


if (menu.classList.contains('show')) {
 menu.classList.remove('show');
 button.innerHTML = '☰ メニューを開く ▼';
 setTimeout(function () {
  menu.style.display = 'none';
 }, 300);
} else {
 menu.style.display = 'block';
 button.innerHTML = '× メニューを閉じる ▲';
 setTimeout(function () {
  menu.classList.add('show');
 }, 10);
}

   

メニューのクラスリストに 'show' が含まれているかをチェックします。
含まれている場合、メニューから 'show' クラスを削除し、ボタンのテキストを変更し、300ミリ秒後にメニューを非表示にします。
含まれていない場合、メニューを表示し、ボタンのテキストを変更し、10ミリ秒後にメニューに 'show' クラスを追加します。

toggleSubMenu関数

function toggleSubMenu(id, buttonId) {
 var submenu = document.getElementById(id);
 var button = document.getElementById(buttonId);
 if (submenu.classList.contains('show')) {
  submenu.classList.remove('show');
  button.innerHTML = button.innerHTML.replace('▲', '▼');
  setTimeout(function () {
   submenu.style.display = 'none';
  }, 300);
 } else {
  submenu.style.display = 'block';
  button.innerHTML = button.innerHTML.replace('▼', '▲');
  setTimeout(function () {
   submenu.classList.add('show');
  }, 10);
 }
}

1. サブメニューとボタンの取得


var submenu = document.getElementById(id);
var button = document.getElementById(buttonId);
   

submenu には指定されたIDの要素を取得します。
button には指定されたIDのボタン要素を取得します。

2. サブメニューの表示/非表示を切り替え


if (submenu.classList.contains('show')) {
 submenu.classList.remove('show');
 button.innerHTML = button.innerHTML.replace('▲', '▼');
 setTimeout(function () {
  submenu.style.display = 'none';
 }, 300);
} else {
 submenu.style.display = 'block';
 button.innerHTML = button.innerHTML.replace('▼', '▲');
 setTimeout(function () {
  submenu.classList.add('show');
 }, 10);
}
   

サブメニューのクラスリストに 'show' が含まれているかをチェックします。
含まれている場合、サブメニューから 'show' クラスを削除し、ボタンのテキストを変更し、300ミリ秒後にサブメニューを非表示にします。
含まれていない場合、サブメニューを表示し、ボタンのテキストを変更し、10ミリ秒後にサブメニューに 'show' クラスを追加します。

DOMContentLoadedイベントとその他のイベントリスナー

document.addEventListener('DOMContentLoaded', function () {
 fetch('../menu/menu.html')
  .then(response => response.text())
  .then(data => {
   document.getElementById('fden-menu-content').innerHTML = data;
  });

 document.addEventListener('click', function (event) {
  var menu = document.getElementById('fden-menu');
  var button = document.getElementById('fden-hamburger-button');
  var isClickInside = menu.contains(event.target) || button.contains(event.target);
  if (!isClickInside && menu.classList.contains('show')) {
   menu.classList.remove('show');
   button.innerHTML = '☰ メニューを開く ▼';
   setTimeout(function () {
    menu.style.display = 'none';
   }, 300);
  }
 });
});

1. DOMContentLoaded イベント


document.addEventListener('DOMContentLoaded', function () {
 fetch('../menu/menu.html')
  .then(response => response.text())
  .then(data => {
   document.getElementById('fden-menu-content').innerHTML = data;
  });
   

ページのDOMが完全に読み込まれた後に実行される関数を設定します。
fetch メソッドで ../menu/menu.html ファイルを取得し、その内容を fden-menu-content 要素に挿入します。

2. クリックイベント


document.addEventListener('click', function (event) {
 var menu = document.getElementById('fden-menu');
 var button = document.getElementById('fden-hamburger-button');
 var isClickInside = menu.contains(event.target) || button.contains(event.target);
 if (!isClickInside && menu.classList.contains('show')) {
  menu.classList.remove('show');
  button.innerHTML = '☰ メニューを開く ▼';
  setTimeout(function () {
   menu.style.display = 'none';
  }, 300);
 }
});
   

ドキュメント全体に対してクリックイベントリスナーを追加します。
クリックがメニューまたはボタンの内部でない場合、メニューを閉じる処理を行います。

htmlファイルを多数のWebページで共有する

フェードアウト効果の草花写真

このハンバーガーメニューでやっているのは、htmlファイルを多数のWebページで共有するというものです。
これをやらないと、メンテナンスに異常に時間がかかるWebサイトになってしまうんですよね。
メニューの中身となるhtmlファイルを別途用意しておいて、それをJavaScriptを用いて各ページに差し込んでいく。
そうすることで、メニューの中身となるhtmlファイルを書き換えれば全てのWebページに中身が反映されます。
特にこういうハンバーガーメニューみたいな階層構造になっているメニューの場合、そのように作り込んでおけば、後がラクでしょ?


サイトマップ

全ページをリスト化したサイトマップも用意していますが、けっこうなページ数があります。
下記の「カテゴリー分けサイトマップ」のほうが使いやすいでしょう。

アナザーエデン関連ページ・サイトマップ
アナザーエデンの強敵戦やストーリーコンテンツのリスト、お勧めバッジなどを掲載したコーナーです。
期間限定のない普通のRPGですので、初心者でも安心して続けていけるゲームとなっています。
もっとも重要なグラスタについては、場所別に網羅した表があります。

個人サイトのホスティングとコンテンツ作成
個人でウェブサイトを作るなら時間をかけて。
HTML・CSS・JavaScriptの書き方はもちろん、無料かつ広告なしでホームページを作る方法を掲載したコーナーです。
Webデザインやレイアウトについても書いてあります。

魚釣りなどアウトドアのエリア
ゲームとパソコンだけじゃなく、アウトドアも趣味なんです。
このコーナーでは魚釣りの記録とか、魚料理のレシピ、はたまたサイクリングなどなど。
アウトドアに関連するコンテンツが詰め込まれています。