📱 第十三章: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-centerPCでは迫力があるのですが、スマホではフォントが大きすぎて画面からはみ出します!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設定から始め、以下を実現しました:
- データベース連携 (Supabase)
- 高級グラスモーフィズムレイアウト (Bento Grid)
- ミリオン級トランジションアニメーション (Framer Motion)
- 完璧なモバイル対応と細部の最適化 (RWD + Scroll Lock)
今、あなたは単なるおもちゃのプロジェクトではなく、「実際のクライアントに販売できる」高級SaaS公式サイトのプロトタイプを完成させました。
これがVibe Codingの真髄です��z-indexのデフォルト値を暗記する必要も、overflow: hiddenを手書きする必要もありません。あなたが知る必要があるのは、「どのような細部がサイトを高級に見せるか?」(例:背景スクロール防止、スムーズなアニメーション追加)だけです。
これらの「ビジネス上の要件」を知っていれば、正確なプロンプトでAIにコードを書かせることができます。
さらに面白いインタラクティブロジックに挑戦したい方は、次の上級プロジェクトへどうぞ:キャンプスポットマップとAI記事連携(Map & AI Articles)。地図上にポイントを配置し、AIにキャンプ推薦記事を自動執筆させる方法を教えます!次回のレッスンでお会いしましょう!