レスポンシブ・ナビバー

ロゴ・メニュー・CTAを横並びに表示するナビバー。画面が狭くなるとハンバーガーボタンに切り替わり、タップで全幅ドロワーメニューがふわりと展開します。

#css#js#nav#responsive

ライブデモ

コード

HTML
<!-- 幅に応じて横並びメニュー⇄ハンバーガー+ドロワーを切り替えるレスポンシブ・ナビバー -->
<div class="nnr-frame" id="nnrFrame">
  <header class="nnr-head">
    <a class="nnr-logo" href="#" onclick="return false"><span class="nnr-logo__mark">◆</span>Arcadia</a>
    <nav class="nnr-nav" aria-label="メインナビゲーション">
      <a href="#" onclick="return false" aria-current="page">ホーム</a>
      <a href="#" onclick="return false">プロダクト</a>
      <a href="#" onclick="return false">料金</a>
      <a href="#" onclick="return false">導入事例</a>
      <a href="#" onclick="return false">会社情報</a>
    </nav>
    <div class="nnr-actions">
      <a class="nnr-cta" href="#" onclick="return false">無料で始める</a>
      <button class="nnr-burger" id="nnrBurger" type="button" aria-label="メニューを開く" aria-expanded="false" aria-controls="nnrDrawer">
        <span></span><span></span><span></span>
      </button>
    </div>
  </header>

  <div class="nnr-overlay" id="nnrOverlay" aria-hidden="true"></div>
  <nav class="nnr-drawer" id="nnrDrawer" aria-label="モバイルメニュー" aria-hidden="true">
    <a href="#" onclick="return false" style="--i:0" aria-current="page">ホーム</a>
    <a href="#" onclick="return false" style="--i:1">プロダクト</a>
    <a href="#" onclick="return false" style="--i:2">料金</a>
    <a href="#" onclick="return false" style="--i:3">導入事例</a>
    <a href="#" onclick="return false" style="--i:4">会社情報</a>
    <a class="nnr-drawer__cta" href="#" onclick="return false" style="--i:5">無料で始める</a>
  </nav>

  <div class="nnr-stage">
    <p class="nnr-hint">画面幅が広いと横並びメニュー、狭くなるとハンバーガー→ドロワーに切り替わります。<br><small>(このプレビュー幅に応じて自動的に表示が変わります)</small></p>
  </div>
</div>
CSS
* { box-sizing: border-box; }
body { margin: 0; display: block; background: #f7faf9; font-family: "Hiragino Sans", "Segoe UI", system-ui, sans-serif; }

/* ルート: width:100% + height:100vh でカード/モーダルどちらの枠にも隙間なく収まる */
.nnr-frame { position: relative; width: 100%; height: 100vh; overflow: hidden; background: #f7faf9; }

.nnr-head {
  position: relative; z-index: 20;
  display: flex; align-items: center; gap: 18px;
  height: 62px; padding: 0 22px;
  background: #fff; border-bottom: 1px solid #e3ece9;
}
.nnr-logo { display: flex; align-items: center; gap: 7px; font-size: 18px; font-weight: 800; color: #0f2b25; text-decoration: none; letter-spacing: -.01em; flex-shrink: 0; }
.nnr-logo__mark { color: #0d9488; font-size: 15px; }

.nnr-nav { display: flex; align-items: center; gap: 4px; }
.nnr-nav a {
  position: relative; font-size: 13.5px; font-weight: 600; color: #3f5852;
  text-decoration: none; padding: 8px 12px; border-radius: 8px; white-space: nowrap;
  transition: background .18s ease, color .18s ease;
}
.nnr-nav a:hover { background: #eef7f5; color: #0d9488; }
.nnr-nav a[aria-current="page"] { color: #0d9488; }
.nnr-nav a[aria-current="page"]::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: 3px; height: 2px;
  background: #0d9488; border-radius: 2px;
}

.nnr-actions { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.nnr-cta {
  font-size: 13px; font-weight: 700; color: #fff; text-decoration: none; white-space: nowrap;
  padding: 9px 18px; border-radius: 999px;
  background: linear-gradient(120deg, #0d9488, #059669);
  transition: filter .15s ease, transform .15s ease;
}
.nnr-cta:hover { filter: brightness(1.08); transform: translateY(-1px); }

/* ハンバーガー:3本線 → X へモーフ。狭幅でのみ表示 */
.nnr-burger { display: none; width: 38px; height: 38px; position: relative; background: none; border: none; cursor: pointer; padding: 0; flex-shrink: 0; }
.nnr-burger span {
  position: absolute; left: 8px; right: 8px; height: 2px; background: #12312b; border-radius: 2px;
  transition: transform .3s ease, opacity .2s ease;
}
.nnr-burger span:nth-child(1) { top: 13px; }
.nnr-burger span:nth-child(2) { top: 18px; }
.nnr-burger span:nth-child(3) { top: 23px; }
.nnr-frame.is-open .nnr-burger span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nnr-frame.is-open .nnr-burger span:nth-child(2) { opacity: 0; }
.nnr-frame.is-open .nnr-burger span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* ドロワー:ヘッダー直下からフルワイドで展開 */
.nnr-overlay {
  position: absolute; inset: 62px 0 0 0; z-index: 15;
  background: rgba(10, 30, 25, .28); opacity: 0; pointer-events: none;
  transition: opacity .25s ease;
}
.nnr-frame.is-open .nnr-overlay { opacity: 1; pointer-events: auto; }

.nnr-drawer {
  position: absolute; top: 62px; left: 0; right: 0; z-index: 18;
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px; background: #fff; border-bottom: 1px solid #e3ece9;
  box-shadow: 0 20px 40px rgba(10, 40, 32, .14);
  transform: translateY(-8px); opacity: 0; pointer-events: none;
  transition: transform .25s ease, opacity .2s ease;
}
.nnr-frame.is-open .nnr-drawer { transform: translateY(0); opacity: 1; pointer-events: auto; }
.nnr-drawer a {
  --d: calc(var(--i, 0) * 45ms);
  font-size: 14px; font-weight: 600; color: #1c3a33; text-decoration: none;
  padding: 12px 14px; border-radius: 9px;
  opacity: 0; transform: translateY(-6px);
  transition: background .18s ease, opacity .3s ease var(--d), transform .3s ease var(--d);
}
.nnr-frame.is-open .nnr-drawer a { opacity: 1; transform: translateY(0); }
.nnr-drawer a:hover { background: #eef7f5; }
.nnr-drawer a[aria-current="page"] { color: #0d9488; }
.nnr-drawer__cta { margin-top: 6px; text-align: center; color: #fff !important; background: linear-gradient(120deg, #0d9488, #059669); }

.nnr-stage { display: grid; place-content: center; height: calc(100% - 62px); text-align: center; padding: 24px; }
.nnr-hint { color: #4b6961; font-size: 13.5px; line-height: 1.8; max-width: 380px; margin: 0; }
.nnr-hint small { color: #7c948c; }

@media (max-width: 680px) {
  .nnr-nav, .nnr-cta { display: none; }
  .nnr-burger { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .nnr-drawer, .nnr-drawer a, .nnr-overlay, .nnr-burger span, .nnr-cta { transition: none; }
}
JavaScript
// ハンバーガー⇄ドロワーの開閉。狭幅の時だけ自動デモも実演し、実操作が来たら止まる(null安全)
(() => {
  const frame = document.getElementById('nnrFrame');
  const burger = document.getElementById('nnrBurger');
  const overlay = document.getElementById('nnrOverlay');
  const drawer = document.getElementById('nnrDrawer');
  if (!frame || !burger) return;

  const set = (open) => {
    frame.classList.toggle('is-open', open);
    burger.setAttribute('aria-expanded', open ? 'true' : 'false');
    if (overlay) overlay.setAttribute('aria-hidden', open ? 'false' : 'true');
    if (drawer) drawer.setAttribute('aria-hidden', open ? 'false' : 'true');
  };

  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  burger.addEventListener('click', () => { auto = false; set(!frame.classList.contains('is-open')); });
  if (overlay) overlay.addEventListener('click', () => { auto = false; set(false); });
  if (drawer) drawer.querySelectorAll('a').forEach((a) => a.addEventListener('click', () => { auto = false; set(false); }));

  const isMobile = () => getComputedStyle(burger).display !== 'none';

  if (auto) {
    let open = false;
    const tick = () => {
      if (!auto || !isMobile()) return;
      open = !open;
      set(open);
      setTimeout(tick, open ? 2200 : 1400);
    };
    setTimeout(tick, 1000);
  }
})();

🤖 AIエージェント用プロンプト

このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「レスポンシブ・ナビバー」の効果を追加してください。

# 追加してほしい効果
レスポンシブ・ナビバー(ヘッダー & ナビ)
ロゴ・メニュー・CTAを横並びに表示するナビバー。画面が狭くなるとハンバーガーボタンに切り替わり、タップで全幅ドロワーメニューがふわりと展開します。

# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 幅に応じて横並びメニュー⇄ハンバーガー+ドロワーを切り替えるレスポンシブ・ナビバー -->
<div class="nnr-frame" id="nnrFrame">
  <header class="nnr-head">
    <a class="nnr-logo" href="#" onclick="return false"><span class="nnr-logo__mark">◆</span>Arcadia</a>
    <nav class="nnr-nav" aria-label="メインナビゲーション">
      <a href="#" onclick="return false" aria-current="page">ホーム</a>
      <a href="#" onclick="return false">プロダクト</a>
      <a href="#" onclick="return false">料金</a>
      <a href="#" onclick="return false">導入事例</a>
      <a href="#" onclick="return false">会社情報</a>
    </nav>
    <div class="nnr-actions">
      <a class="nnr-cta" href="#" onclick="return false">無料で始める</a>
      <button class="nnr-burger" id="nnrBurger" type="button" aria-label="メニューを開く" aria-expanded="false" aria-controls="nnrDrawer">
        <span></span><span></span><span></span>
      </button>
    </div>
  </header>

  <div class="nnr-overlay" id="nnrOverlay" aria-hidden="true"></div>
  <nav class="nnr-drawer" id="nnrDrawer" aria-label="モバイルメニュー" aria-hidden="true">
    <a href="#" onclick="return false" style="--i:0" aria-current="page">ホーム</a>
    <a href="#" onclick="return false" style="--i:1">プロダクト</a>
    <a href="#" onclick="return false" style="--i:2">料金</a>
    <a href="#" onclick="return false" style="--i:3">導入事例</a>
    <a href="#" onclick="return false" style="--i:4">会社情報</a>
    <a class="nnr-drawer__cta" href="#" onclick="return false" style="--i:5">無料で始める</a>
  </nav>

  <div class="nnr-stage">
    <p class="nnr-hint">画面幅が広いと横並びメニュー、狭くなるとハンバーガー→ドロワーに切り替わります。<br><small>(このプレビュー幅に応じて自動的に表示が変わります)</small></p>
  </div>
</div>

【CSS】
* { box-sizing: border-box; }
body { margin: 0; display: block; background: #f7faf9; font-family: "Hiragino Sans", "Segoe UI", system-ui, sans-serif; }

/* ルート: width:100% + height:100vh でカード/モーダルどちらの枠にも隙間なく収まる */
.nnr-frame { position: relative; width: 100%; height: 100vh; overflow: hidden; background: #f7faf9; }

.nnr-head {
  position: relative; z-index: 20;
  display: flex; align-items: center; gap: 18px;
  height: 62px; padding: 0 22px;
  background: #fff; border-bottom: 1px solid #e3ece9;
}
.nnr-logo { display: flex; align-items: center; gap: 7px; font-size: 18px; font-weight: 800; color: #0f2b25; text-decoration: none; letter-spacing: -.01em; flex-shrink: 0; }
.nnr-logo__mark { color: #0d9488; font-size: 15px; }

.nnr-nav { display: flex; align-items: center; gap: 4px; }
.nnr-nav a {
  position: relative; font-size: 13.5px; font-weight: 600; color: #3f5852;
  text-decoration: none; padding: 8px 12px; border-radius: 8px; white-space: nowrap;
  transition: background .18s ease, color .18s ease;
}
.nnr-nav a:hover { background: #eef7f5; color: #0d9488; }
.nnr-nav a[aria-current="page"] { color: #0d9488; }
.nnr-nav a[aria-current="page"]::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: 3px; height: 2px;
  background: #0d9488; border-radius: 2px;
}

.nnr-actions { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.nnr-cta {
  font-size: 13px; font-weight: 700; color: #fff; text-decoration: none; white-space: nowrap;
  padding: 9px 18px; border-radius: 999px;
  background: linear-gradient(120deg, #0d9488, #059669);
  transition: filter .15s ease, transform .15s ease;
}
.nnr-cta:hover { filter: brightness(1.08); transform: translateY(-1px); }

/* ハンバーガー:3本線 → X へモーフ。狭幅でのみ表示 */
.nnr-burger { display: none; width: 38px; height: 38px; position: relative; background: none; border: none; cursor: pointer; padding: 0; flex-shrink: 0; }
.nnr-burger span {
  position: absolute; left: 8px; right: 8px; height: 2px; background: #12312b; border-radius: 2px;
  transition: transform .3s ease, opacity .2s ease;
}
.nnr-burger span:nth-child(1) { top: 13px; }
.nnr-burger span:nth-child(2) { top: 18px; }
.nnr-burger span:nth-child(3) { top: 23px; }
.nnr-frame.is-open .nnr-burger span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nnr-frame.is-open .nnr-burger span:nth-child(2) { opacity: 0; }
.nnr-frame.is-open .nnr-burger span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* ドロワー:ヘッダー直下からフルワイドで展開 */
.nnr-overlay {
  position: absolute; inset: 62px 0 0 0; z-index: 15;
  background: rgba(10, 30, 25, .28); opacity: 0; pointer-events: none;
  transition: opacity .25s ease;
}
.nnr-frame.is-open .nnr-overlay { opacity: 1; pointer-events: auto; }

.nnr-drawer {
  position: absolute; top: 62px; left: 0; right: 0; z-index: 18;
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px; background: #fff; border-bottom: 1px solid #e3ece9;
  box-shadow: 0 20px 40px rgba(10, 40, 32, .14);
  transform: translateY(-8px); opacity: 0; pointer-events: none;
  transition: transform .25s ease, opacity .2s ease;
}
.nnr-frame.is-open .nnr-drawer { transform: translateY(0); opacity: 1; pointer-events: auto; }
.nnr-drawer a {
  --d: calc(var(--i, 0) * 45ms);
  font-size: 14px; font-weight: 600; color: #1c3a33; text-decoration: none;
  padding: 12px 14px; border-radius: 9px;
  opacity: 0; transform: translateY(-6px);
  transition: background .18s ease, opacity .3s ease var(--d), transform .3s ease var(--d);
}
.nnr-frame.is-open .nnr-drawer a { opacity: 1; transform: translateY(0); }
.nnr-drawer a:hover { background: #eef7f5; }
.nnr-drawer a[aria-current="page"] { color: #0d9488; }
.nnr-drawer__cta { margin-top: 6px; text-align: center; color: #fff !important; background: linear-gradient(120deg, #0d9488, #059669); }

.nnr-stage { display: grid; place-content: center; height: calc(100% - 62px); text-align: center; padding: 24px; }
.nnr-hint { color: #4b6961; font-size: 13.5px; line-height: 1.8; max-width: 380px; margin: 0; }
.nnr-hint small { color: #7c948c; }

@media (max-width: 680px) {
  .nnr-nav, .nnr-cta { display: none; }
  .nnr-burger { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .nnr-drawer, .nnr-drawer a, .nnr-overlay, .nnr-burger span, .nnr-cta { transition: none; }
}

【JavaScript】
// ハンバーガー⇄ドロワーの開閉。狭幅の時だけ自動デモも実演し、実操作が来たら止まる(null安全)
(() => {
  const frame = document.getElementById('nnrFrame');
  const burger = document.getElementById('nnrBurger');
  const overlay = document.getElementById('nnrOverlay');
  const drawer = document.getElementById('nnrDrawer');
  if (!frame || !burger) return;

  const set = (open) => {
    frame.classList.toggle('is-open', open);
    burger.setAttribute('aria-expanded', open ? 'true' : 'false');
    if (overlay) overlay.setAttribute('aria-hidden', open ? 'false' : 'true');
    if (drawer) drawer.setAttribute('aria-hidden', open ? 'false' : 'true');
  };

  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  burger.addEventListener('click', () => { auto = false; set(!frame.classList.contains('is-open')); });
  if (overlay) overlay.addEventListener('click', () => { auto = false; set(false); });
  if (drawer) drawer.querySelectorAll('a').forEach((a) => a.addEventListener('click', () => { auto = false; set(false); }));

  const isMobile = () => getComputedStyle(burger).display !== 'none';

  if (auto) {
    let open = false;
    const tick = () => {
      if (!auto || !isMobile()) return;
      open = !open;
      set(open);
      setTimeout(tick, open ? 2200 : 1400);
    };
    setTimeout(tick, 1000);
  }
})();

# 外部ライブラリ
なし(追加ライブラリ不要)

# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。