📱 第十三章:RWD レスポンシブデザインとマジカルハンバーガーメニュー

27インチのモニターでキャンプサイトを完璧に仕上げた数時間後。 あなたはワクワクしながら上司にURLを送信し、上司がiPhoneで開くと「これは何だ?文字が全部重なって、画像も画面からはみ出している!」と眉をひそめました。

これが全てのフロントエンドエンジニアの悪夢です:レスポンシブデザイン(Responsive Web Design、略してRWD)が実装されていない

以前は、サイトをスマホ、タブレット、PCの3つの画面サイズに対応させるために、複数のmedia queryCSSファイルを書く必要があり、非常に苦痛でした。 しかし今、私たちにはTailwind CSSがあります!AIの力を借りれば、RWDは朝飯前です。

このレッスンでは、5つのVibeプロンプトを使って、スマホ版のレイアウト崩れを一瞬で修正し、あの定番の「ハンバーガーメニュー(Hamburger Menu)」を実装する方法を学びます!


📐 実践1:Tailwindのブレークポイントマジックをマスター

TailwindにおけるRWDの核心概念はプレフィックスです:

  • 何も付けない(デフォルト)= モバイル版 (Mobile-firstの考え方)
  • md: = タブレット版 (Medium)
  • lg: = PC版 (Large)

💡 Vibeプロンプト実践1:文字が重なる問題を一瞬で解決

[!IMPORTANT] 以下のプロンプトをAIにコピーして送信してください:

キャンプサイトのタイトルをデザイン中です。現在のclassは:text-6xl font-bold text-center PCでは迫力があるのですが、スマホではフォントが大きすぎて画面からはみ出します! TailwindのRWD記法(sm, md, lg)を使って修正してください。 要件: 1. モバイル版(デフォルト)では少し小さく、text-3xlを使用。 2. タブレット以上(md:)ではtext-5xl。 3. PC以上(lg:)ではtext-7xl。 修正後のdiv行を直接教えてください。

🤖 AIが生成したレスポンシブコード:

<!-- 旧記法:モバイルでレイアウト崩れ -->
<h1 class="text-6xl font-bold text-center">未知のキャンプ場を探検</h1>

<!-- 🔥 AI修正後のRWD記法:画面サイズに応じて自動調整! -->
<h1 class="text-3xl md:text-5xl lg:text-7xl font-bold text-center">未知のキャンプ場を探検</h1>

🔍 詳細解説: これが「Mobile-first(モバイルファースト)」の考え方です。最初に設定したtext-3xlはモバイル用です。画面サイズが大きくなりmd:(タブレット)のブレークポイントを超えると、Tailwindが自動的にtext-5xlで上書きします。もう複雑な@media (min-width: 768px)を自分で書く必要はありません!


🍔 実践2:ゼロから「マジカルハンバーガーメニュー」を作成

PC版では、ナビゲーションバー(Navbar)に「ホーム」「キャンプ場一覧」「ログイン」「登録」など多くのボタンがあり、横並びで表示されます。 しかしモバイル版では、幅が足りません!この場合、「三本線のハンバーガーアイコン(Hamburger Icon)」が必要です。これをクリックすると、メニューがスライドして表示されます。

これはReactの状態(State)管理が関わってきます。初心者には難しいですが、AIにとっては朝飯前です。

💡 Vibeプロンプト実践2:AIにロジックのあるハンバーガーメニューを書かせる

[!IMPORTANT] 以下のプロンプトをAIにコピーして送信してください:

Reactでナビゲーションバー(Navbar)を実装したいです。 要件は以下の通り: 1. PC版(md:以上)では、メニューリンク("ホーム","探検","ログイン")を右側に横並び。 2. モバイル版ではこれらのリンクを非表示にし、「ハンバーガーアイコンボタン(三本線)」を表示。 3. useStateでisOpen状態を宣言し、デフォルトはfalse。 4. ハンバーガーボタンクリックでisOpen状態をトグル。 5. isOpenがtrueの場合、ナビゲーションバー下部に全幅の縦型メニューを表示。 完全なReactコンポーネントコードを教えてください。

🤖 AIが生成した実際のコード(構造解析):

import React, { useState } from 'react';

export default function Navbar() {
  // モバイルメニューの開閉を制御する要!
  const [isOpen, setIsOpen] = useState(false);

  return (
    <nav className="bg-zinc-900 border-b border-zinc-800 p-4">
      <div className="max-w-6xl mx-auto flex justify-between items-center">
        {/* 左側ロゴ */}
        <div className="text-xl font-bold text-white">🏕️ キャンプ楽</div>

        {/* PC版メニュー (モバイル非表示 md:flex、タブレット以上で表示) */}
        <div className="hidden md:flex gap-6 text-zinc-300">
          <a href="#" className="hover:text-white">ホーム</a>
          <a href="#" className="hover:text-white">探検</a>
          <a href="#" className="hover:text-white">ログイン</a>
        </div>

        {/* モバイル版ハンバーガーボタン (タブレット以上非表示 md:hidden) */}
        <button 
          className="md:hidden text-white text-2xl"
          onClick={() => setIsOpen(!isOpen)}
        >
          {/* 開いている場合は✕、閉じている場合は☰ */}
          {isOpen ? "✕" : "☰"}
        </button>
      </div>

      {/* モバイル版縦型ドロップダウンメニュー (条件付きレンダリング:isOpenがtrueの場合のみ表示) */}
      {isOpen && (
        <div className="md:hidden mt-4 flex flex-col gap-4 text-center pb-4 text-zinc-300">
          <a href="#" className="hover:text-white border-b border-zinc-800 pb-2">ホーム</a>
          <a href="#" className="hover:text-white border-b border-zinc-800 pb-2">探検</a>
          <a href="#" className="hover:text-white pb-2">ログイン</a>
        </div>
      )}
    </nav>
  );
}

✨ 実践3:動きが硬い!Framer Motionでメニューにアニメーションを追加

上記のハンバーガーメニューは機能しますが、表示方法が「瞬間的に現れる」ため、高級感がありません。 Vibe Coderとして、このような生硬な体験は許容できません。 Reactアニメーション界の覇者Framer Motionを導入し、メニューが「スライドイン」する優雅な登場演出を追加しましょう!

💡 Vibeプロンプト実践3:滑らかなアニメーションを注入

[!IMPORTANT] 以下のプロンプトをAIにコピーして送信してください:

モバイル版縦型メニュー(isOpenで表示制御)を実装しました。 しかし表示が瞬間的で硬い印象です。 'framer-motion'ライブラリを導入し(<AnimatePresence>と<motion.div>を使用)、 モバイルメニューに以下のアニメーション効果を追加したいです: 1. 初期状態(initial):高さ0、透明度0 (opacity: 0, height: 0) 2. 表示状態(animate):高さauto、透明度1 (opacity: 1, height: "auto") 3. 非表示状態(exit):高さ0、透明度0に戻る Navbarコンポーネントを修正してください。

🤖 AIアニメーションマスターの作品:

import React, { useState } from 'react';
// 🔥 Framer Motionアニメーション神器を導入
import { motion, AnimatePresence } from 'framer-motion';

export default function Navbar() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <nav className="bg-zinc-900 border-b border-zinc-800 p-4 relative z-50">
      {/* ...上部のロゴとボタン部分は変更なし... */}

      {/* AnimatePresenceでラップ - コンポーネント「非表示時」にもアニメーションを可能にする鍵 */}
      <AnimatePresence>
        {isOpen && (
          <motion.div 
            initial={{ opacity: 0, height: 0 }}
            animate={{ opacity: 1, height: "auto" }}
            exit={{ opacity: 0, height: 0 }}
            transition={{ duration: 0.3, ease: "easeInOut" }}
            className="md:hidden overflow-hidden mt-4 flex flex-col gap-4 text-center text-zinc-300"
          >
            {/* メニュー内容 */}
            <div className="py-4 space-y-4">
              <a href="#" className="block hover:text-white">ホーム</a>
              <a href="#" className="block hover:text-white">探検</a>
              <a href="#" className="block hover:text-white">ログイン</a>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </nav>
  );
}

🔍 詳細解説: 見ましたか?これが価値です!一般的な初心者エンジニアは、「高さ0からautoへのアニメーションが効かない」というCSSの千古の難題に3日間も悩むかもしれません。 しかしFramer MotionとAIの力を借りれば、わずか1〜2分で、Appleの公式サイトのような滑らかなモバイルドロップダウンメニューが完成します!


🚫 究極の落とし穴回避ガイド:Z-index地獄

美しいハンバーガーメニューを作成した後、最もよく起こる災難は:「メニューが開いたのに、下の地図や画像に遮られる!」 ユーザーが「ログイン」をクリックしようとして、背後にある「地図拡大」ボタンを押してしまう現象です。

これはCSSのz-index(重なり順)が正しく設定されていないためです。

💡 Vibeプロンプト実践4:メニューが遮られる問題を解決

[!IMPORTANT] 以下のプロンプトをAIにコピーして送信してください:

Navbarのハンバーガーメニューを開くと、ドロップダウン内容が下のLeaflet地図ブロックに遮られてしまいます! Tailwindのclassを使って、Navbarが常に画面最前面に表示されるようにするには? <nav>タグに追加する具体的なClassを教えてください。

🤖 AIのレイアウト救済:

<!-- ❌ 旧記法:階層不足で地図に食べられる -->
<nav class="bg-zinc-900 p-4">

<!-- ✅ 正しい記法:relativeまたはfixedを追加し、非常に高いz-indexを設定 -->
<nav class="bg-zinc-900 p-4 relative z-[999]">

<!--
【AI詳細解説】:
z-index(重なり順序)はミルフィーユのようなものです。数字が大きいほど上層に。
Leaflet地図や絶対配置��れた画像は、デフォルトでz-index(例:400)を持っています。
Navbarにz-indexを設定しないと、地図の下に隠れてしまいます。
`relative z-[999]`を追加すれば、ナビゲーションバーが常に最前面に表示されます!
-->

🔒 上級者向けUX最適化:メニュー開閉時の背景スクロール防止

高級サイトの隠れた細部:モバイル版ハンバーガーメニューが全画面で開いた時、誤って画面をスクロールさせても、背後にあるサイトコンテンツがスクロールしないようにする必要があります!これがないとサイトが安っぽく見えます。

💡 Vibeプロンプト実践5:背景スクロールをブロック

[!IMPORTANT] 以下のプロンプトをAIにコピーして送信してください:

モバイル版ハンバーガーメニューが開いた時(isOpenがtrue)、背後にあるページ全体がスクロールしないようにしたいです。 ReactのuseEffectロジックを書いてください。 isOpen === trueの場合、bodyのoverflowを'hidden'に設定。 isOpen === falseまたはコンポーネントがアンマウントされた時、bodyのoverflowを'auto'に戻します。

🤖 AIによる詳細なUXアップグレー���:

  // Navbarコンポーネント内に配置
  useEffect(() => {
    if (isOpen) {
      // 背景をロックし、スクロール禁止
      document.body.style.overflow = 'hidden';
    } else {
      // 通常のスクロールに戻す
      document.body.style.overflow = 'auto';
    }

    // 💡 クリーンアップ関数:
    // ユーザーがページを切り替えたり、Navbarが破棄された時に背景が永遠にロックされないように
    return () => {
      document.body.style.overflow = 'auto';
    };
  }, [isOpen]); // isOpenが変更されるたびにこのEffectが発火

✅ 本章のまとめと実践完了

**キャンプ公式サイト構築(Camping Official Site)**の全13章を完了しました! 私たちは基本的なAstro設定から始め、以下を実現しました:

  1. データベース連携 (Supabase)
  2. 高級グラスモーフィズムレイアウト (Bento Grid)
  3. ミリオン級トランジションアニメーション (Framer Motion)
  4. 完璧なモバイル対応と細部の最適化 (RWD + Scroll Lock)

今、あなたは単なるおもちゃのプロジェクトではなく、「実際のクライアントに販売できる」高級SaaS公式サイトのプロトタイプを完成させました。

これがVibe Codingの真髄です��z-indexのデフォルト値を暗記する必要も、overflow: hiddenを手書きする必要もありません。あなたが知る必要があるのは、「どのような細部がサイトを高級に見せるか?」(例:背景スクロール防止、スムーズなアニメーション追加)だけです。 これらの「ビジネス上の要件」を知っていれば、正確なプロンプトでAIにコードを書かせることができます。

さらに面白いインタラクティブロジックに挑戦したい方は、次の上級プロジェクトへどうぞ:キャンプスポットマップとAI記事連携(Map & AI Articles)。地図上にポイントを配置し、AIにキャンプ推薦記事を自動執筆させる方法を教えます!次回のレッスンでお会いしましょう!

完全なチュートリアルをロック解除

このチャプターは有料コンテンツです。プロジェクトに参加して、10以上の神レベルのPromptや実際のソースコード例を含む、5000字以上の深い分析をロック解除してください!