ヘッダー 初級

小型ドロップダウンナビ

メガメニューほど大きくない、項目ごとの小さなドロップダウン。ホバー/フォーカスで数件のサブリンクをふわっと出します。情報量が中程度のサイトでちょうどよい、扱いやすいナビです。

#header#dropdown#navigation#menu

ライブデモ

使用例(お題: カフェ MOON BREW)

この技法を「カフェ MOON BREW」というテーマのダミーサイトで実際に使った例です。

HTML
<!-- MOON BREW:カフェの小型ドロップダウンナビ -->
<div class="hdm-frame">
  <header class="hdm-head">
    <a class="hdm-logo" href="#" onclick="return false">☕ MOON BREW</a>
    <nav class="hdm-nav">
      <div class="hdm-item" id="hdmItem">
        <button class="hdm-trigger" type="button" aria-expanded="false">メニュー <span class="hdm-caret">▾</span></button>
        <div class="hdm-menu" role="menu">
          <a href="#" onclick="return false">コーヒー</a>
          <a href="#" onclick="return false">ラテ・カフェオレ</a>
          <a href="#" onclick="return false">フード</a>
        </div>
      </div>
      <a class="hdm-link" href="#" onclick="return false">豆を買う</a>
      <a class="hdm-link" href="#" onclick="return false">店舗</a>
      <a class="hdm-link" href="#" onclick="return false">物語</a>
    </nav>
    <button class="hdm-cta" type="button">予約する</button>
  </header>
  <div class="hdm-stage">
    <h1>夜にひらく、珈琲店</h1>
    <p>「メニュー」にホバー/フォーカスで小さな下層メニュー。</p>
  </div>
</div>
CSS
/* MOON BREW(カフェ):小型ドロップダウンナビの再スキン */
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.hdm-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: #f7f2e9; }
.hdm-head { position: relative; z-index: 5; display: flex; align-items: center; gap: 20px; height: 60px; padding: 0 24px; background: #fffdf8; border-bottom: 1px solid #ece2d0; }
.hdm-logo { font-size: 18px; font-weight: 800; color: #7a4f2a; text-decoration: none; }
.hdm-nav { display: flex; align-items: center; gap: 4px; }
.hdm-trigger, .hdm-link { font: inherit; font-size: 13.5px; font-weight: 600; color: #5b4630; background: none; border: none; cursor: pointer; text-decoration: none; padding: 8px 12px; border-radius: 8px; display: inline-flex; align-items: center; gap: 5px; transition: background .2s ease, color .2s ease; }
.hdm-trigger:hover, .hdm-link:hover { background: #f1e7d6; color: #7a4f2a; }
.hdm-caret { font-size: 9px; transition: transform .25s ease; }
.hdm-cta { margin-left: auto; font: inherit; font-size: 12.5px; font-weight: 700; color: #fff; background: #7a4f2a; border: none; padding: 9px 17px; border-radius: 999px; cursor: pointer; transition: filter .15s ease, transform .15s ease; }
.hdm-cta:hover { filter: brightness(1.08); transform: translateY(-1px); }

.hdm-item { position: relative; }
.hdm-menu { position: absolute; top: calc(100% + 6px); left: 0; min-width: 178px; background: #fffdf8; border: 1px solid #ece2d0; border-radius: 11px; padding: 6px; box-shadow: 0 16px 34px rgba(90,60,30,.16); opacity: 0; transform: translateY(-6px); pointer-events: none; transition: opacity .2s ease, transform .2s ease; }
.hdm-item:hover .hdm-menu, .hdm-item:focus-within .hdm-menu, .hdm-item.is-open .hdm-menu { opacity: 1; transform: translateY(0); pointer-events: auto; }
.hdm-item:hover .hdm-caret, .hdm-item.is-open .hdm-caret { transform: rotate(180deg); }
.hdm-menu a { display: block; font-size: 13px; color: #5b4630; text-decoration: none; padding: 9px 11px; border-radius: 8px; transition: background .16s ease; }
.hdm-menu a:hover { background: #f3ead9; color: #7a4f2a; }

.hdm-stage { display: grid; place-content: center; height: calc(100% - 60px); text-align: center; color: #4a3320; padding: 0 24px; }
.hdm-stage h1 { margin: 0; font-size: 26px; font-weight: 800; font-family: "Hiragino Mincho ProN", serif; }
.hdm-stage p { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: #8a715a; }

@media (prefers-reduced-motion: reduce) { .hdm-menu, .hdm-caret, .hdm-cta { transition: none; } }
JavaScript
// (デモと同じフックを流用)ホバー/フォーカス+自動開閉で小型ドロップダウン
(() => {
  const item = document.getElementById('hdmItem');
  if (!item) return;
  const trigger = item.querySelector('.hdm-trigger');
  const sync = () => trigger && trigger.setAttribute('aria-expanded', item.classList.contains('is-open') ? 'true' : 'false');
  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  ['pointerenter', 'focusin', 'pointerdown'].forEach(ev => item.addEventListener(ev, () => { auto = false; item.classList.remove('is-open'); sync(); }));
  if (auto) {
    let open = false;
    const tick = () => { if (!auto) return; open = !open; item.classList.toggle('is-open', open); sync(); setTimeout(tick, open ? 2000 : 1400); };
    setTimeout(tick, 1000);
  }
})();

実装ガイド

使いどころ

情報量が中程度のサイトで、メガメニューほど大げさにせず数件のサブリンクを見せたいときに。項目ごとの小さなドロップダウンです。

実装時の注意点

開閉は :hover と :focus-within(CSS)で行い、JS はプレビュー用の自動開閉のみ。パネルは項目基準の絶対配置で、ふわっとフェード+スライドして開きます。

対応ブラウザ

:focus-within・transition は全モダンブラウザ対応。キーボード操作にも反応します。

よくある失敗

ホバーのみだとタッチで使えないため、クリック/タップのフォールバックを。画面端の項目はパネルが切れないよう右寄せに切り替える配慮を。ホバーインテント(遅延)が無いと通過しただけで開いて煩わしくなります。

応用例

アイコン付きリンク、2カラム化、選択中のハイライト、矢印キーでの項目移動などに拡張できます。

コード

HTML
<!-- 項目ごとの小型ドロップダウンナビ -->
<div class="hdm-frame">
  <header class="hdm-head">
    <a class="hdm-logo" href="#" onclick="return false">Pine</a>
    <nav class="hdm-nav">
      <div class="hdm-item" id="hdmItem">
        <button class="hdm-trigger" type="button" aria-expanded="false">サービス <span class="hdm-caret">▾</span></button>
        <div class="hdm-menu" role="menu">
          <a href="#" onclick="return false">サイト制作</a>
          <a href="#" onclick="return false">運用・保守</a>
          <a href="#" onclick="return false">アクセス解析</a>
        </div>
      </div>
      <a class="hdm-link" href="#" onclick="return false">料金</a>
      <a class="hdm-link" href="#" onclick="return false">実績</a>
      <a class="hdm-link" href="#" onclick="return false">会社</a>
    </nav>
    <button class="hdm-cta" type="button">相談する</button>
  </header>

  <div class="hdm-stage">
    <h1>小型ドロップダウン</h1>
    <p>「サービス」にホバー/フォーカスで小さな下層メニュー。<br>(自動でも開閉を実演します)</p>
  </div>
</div>
CSS
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.hdm-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: #f3f6f4; }

.hdm-head { position: relative; z-index: 5; display: flex; align-items: center; gap: 20px; height: 60px; padding: 0 24px; background: #fff; border-bottom: 1px solid #e4ebe6; }
.hdm-logo { font-size: 19px; font-weight: 800; color: #15803d; text-decoration: none; }
.hdm-nav { display: flex; align-items: center; gap: 4px; }

.hdm-trigger, .hdm-link { font: inherit; font-size: 13.5px; font-weight: 600; color: #2f4137; background: none; border: none; cursor: pointer; text-decoration: none; padding: 8px 12px; border-radius: 8px; display: inline-flex; align-items: center; gap: 5px; transition: background .2s ease, color .2s ease; }
.hdm-trigger:hover, .hdm-link:hover { background: #e7f3eb; color: #15803d; }
.hdm-caret { font-size: 9px; transition: transform .25s ease; }

.hdm-cta { margin-left: auto; font: inherit; font-size: 12.5px; font-weight: 700; color: #fff; background: #15803d; border: none; padding: 9px 17px; border-radius: 999px; cursor: pointer; transition: filter .15s ease, transform .15s ease; }
.hdm-cta:hover { filter: brightness(1.08); transform: translateY(-1px); }

/* 小型ドロップダウン */
.hdm-item { position: relative; }
.hdm-menu {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 168px;
  background: #fff; border: 1px solid #e2e8e4; border-radius: 11px; padding: 6px;
  box-shadow: 0 16px 34px rgba(20,40,28,.14);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
.hdm-item:hover .hdm-menu, .hdm-item:focus-within .hdm-menu, .hdm-item.is-open .hdm-menu { opacity: 1; transform: translateY(0); pointer-events: auto; }
.hdm-item:hover .hdm-caret, .hdm-item.is-open .hdm-caret { transform: rotate(180deg); }
.hdm-menu a { display: block; font-size: 13px; color: #2f4137; text-decoration: none; padding: 9px 11px; border-radius: 8px; transition: background .16s ease; }
.hdm-menu a:hover { background: #eef6f0; color: #15803d; }

.hdm-stage { display: grid; place-content: center; height: calc(100% - 60px); text-align: center; color: #243029; padding: 0 24px; }
.hdm-stage h1 { margin: 0; font-size: 26px; font-weight: 800; }
.hdm-stage p { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: #5d6f63; }

@media (prefers-reduced-motion: reduce) { .hdm-menu, .hdm-caret, .hdm-cta { transition: none; } }
JavaScript
// ホバー/フォーカス+自動開閉で小型ドロップダウンを実演
(() => {
  const item = document.getElementById('hdmItem');
  if (!item) return;
  const trigger = item.querySelector('.hdm-trigger');
  const sync = () => trigger && trigger.setAttribute('aria-expanded', item.classList.contains('is-open') ? 'true' : 'false');
  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  ['pointerenter', 'focusin', 'pointerdown'].forEach(ev => item.addEventListener(ev, () => { auto = false; item.classList.remove('is-open'); sync(); }));
  if (auto) {
    let open = false;
    const tick = () => { if (!auto) return; open = !open; item.classList.toggle('is-open', open); sync(); setTimeout(tick, open ? 2000 : 1400); };
    setTimeout(tick, 1000);
  }
})();

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

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

# 追加してほしい効果
小型ドロップダウンナビ(ヘッダー)
メガメニューほど大きくない、項目ごとの小さなドロップダウン。ホバー/フォーカスで数件のサブリンクをふわっと出します。情報量が中程度のサイトでちょうどよい、扱いやすいナビです。

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

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 項目ごとの小型ドロップダウンナビ -->
<div class="hdm-frame">
  <header class="hdm-head">
    <a class="hdm-logo" href="#" onclick="return false">Pine</a>
    <nav class="hdm-nav">
      <div class="hdm-item" id="hdmItem">
        <button class="hdm-trigger" type="button" aria-expanded="false">サービス <span class="hdm-caret">▾</span></button>
        <div class="hdm-menu" role="menu">
          <a href="#" onclick="return false">サイト制作</a>
          <a href="#" onclick="return false">運用・保守</a>
          <a href="#" onclick="return false">アクセス解析</a>
        </div>
      </div>
      <a class="hdm-link" href="#" onclick="return false">料金</a>
      <a class="hdm-link" href="#" onclick="return false">実績</a>
      <a class="hdm-link" href="#" onclick="return false">会社</a>
    </nav>
    <button class="hdm-cta" type="button">相談する</button>
  </header>

  <div class="hdm-stage">
    <h1>小型ドロップダウン</h1>
    <p>「サービス」にホバー/フォーカスで小さな下層メニュー。<br>(自動でも開閉を実演します)</p>
  </div>
</div>

【CSS】
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.hdm-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: #f3f6f4; }

.hdm-head { position: relative; z-index: 5; display: flex; align-items: center; gap: 20px; height: 60px; padding: 0 24px; background: #fff; border-bottom: 1px solid #e4ebe6; }
.hdm-logo { font-size: 19px; font-weight: 800; color: #15803d; text-decoration: none; }
.hdm-nav { display: flex; align-items: center; gap: 4px; }

.hdm-trigger, .hdm-link { font: inherit; font-size: 13.5px; font-weight: 600; color: #2f4137; background: none; border: none; cursor: pointer; text-decoration: none; padding: 8px 12px; border-radius: 8px; display: inline-flex; align-items: center; gap: 5px; transition: background .2s ease, color .2s ease; }
.hdm-trigger:hover, .hdm-link:hover { background: #e7f3eb; color: #15803d; }
.hdm-caret { font-size: 9px; transition: transform .25s ease; }

.hdm-cta { margin-left: auto; font: inherit; font-size: 12.5px; font-weight: 700; color: #fff; background: #15803d; border: none; padding: 9px 17px; border-radius: 999px; cursor: pointer; transition: filter .15s ease, transform .15s ease; }
.hdm-cta:hover { filter: brightness(1.08); transform: translateY(-1px); }

/* 小型ドロップダウン */
.hdm-item { position: relative; }
.hdm-menu {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 168px;
  background: #fff; border: 1px solid #e2e8e4; border-radius: 11px; padding: 6px;
  box-shadow: 0 16px 34px rgba(20,40,28,.14);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
.hdm-item:hover .hdm-menu, .hdm-item:focus-within .hdm-menu, .hdm-item.is-open .hdm-menu { opacity: 1; transform: translateY(0); pointer-events: auto; }
.hdm-item:hover .hdm-caret, .hdm-item.is-open .hdm-caret { transform: rotate(180deg); }
.hdm-menu a { display: block; font-size: 13px; color: #2f4137; text-decoration: none; padding: 9px 11px; border-radius: 8px; transition: background .16s ease; }
.hdm-menu a:hover { background: #eef6f0; color: #15803d; }

.hdm-stage { display: grid; place-content: center; height: calc(100% - 60px); text-align: center; color: #243029; padding: 0 24px; }
.hdm-stage h1 { margin: 0; font-size: 26px; font-weight: 800; }
.hdm-stage p { margin: 12px 0 0; font-size: 13px; line-height: 1.8; color: #5d6f63; }

@media (prefers-reduced-motion: reduce) { .hdm-menu, .hdm-caret, .hdm-cta { transition: none; } }

【JavaScript】
// ホバー/フォーカス+自動開閉で小型ドロップダウンを実演
(() => {
  const item = document.getElementById('hdmItem');
  if (!item) return;
  const trigger = item.querySelector('.hdm-trigger');
  const sync = () => trigger && trigger.setAttribute('aria-expanded', item.classList.contains('is-open') ? 'true' : 'false');
  let auto = !matchMedia('(prefers-reduced-motion: reduce)').matches;
  ['pointerenter', 'focusin', 'pointerdown'].forEach(ev => item.addEventListener(ev, () => { auto = false; item.classList.remove('is-open'); sync(); }));
  if (auto) {
    let open = false;
    const tick = () => { if (!auto) return; open = !open; item.classList.toggle('is-open', open); sync(); setTimeout(tick, open ? 2000 : 1400); };
    setTimeout(tick, 1000);
  }
})();

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

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