ヘッダー 中級

浮遊ピル型ヘッダー

画面上端から少し浮かせた、角丸+影のカプセル状ヘッダー。スクロールすると幅が締まって中央に寄ります。モダンなブランドサイトやポートフォリオで人気の“浮いている”ナビです。

#header#floating#pill#navigation

ライブデモ

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

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

HTML
<!-- MOON BREW:カフェの浮遊ピル型ヘッダー -->
<div class="hpf-frame">
  <header class="hpf-head" id="hpfHead">
    <a class="hpf-logo" href="#" onclick="return false">☕ MOON BREW</a>
    <nav class="hpf-nav">
      <a href="#" onclick="return false">メニュー</a>
      <a href="#" onclick="return false">豆</a>
      <a href="#" onclick="return false">店舗</a>
    </nav>
    <button class="hpf-cta" type="button">予約</button>
  </header>

  <div class="hpf-scroll" id="hpfScroll">
    <section class="hpf-hero">
      <h1>夜にひらく、珈琲店</h1>
      <p>浮いた角丸ナビ。スクロールで幅が締まって中央に寄ります。</p>
    </section>
    <section class="hpf-body">
      <p>深夜焙煎の一杯と、静かな時間を。月替わりのシングルオリジンを店頭・オンラインで。</p>
      <p>スクロールするとピル型ヘッダーが引き締まり、軽やかな余白の中に浮かびます。</p>
      <p>このデモは自動でゆっくり往復し、締まる→戻るの動きを実演します。</p>
    </section>
  </div>
</div>
CSS
/* MOON BREW(カフェ):浮遊ピル型ヘッダーの再スキン */
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.hpf-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: #17110a; }
.hpf-head {
  position: absolute; z-index: 10; top: 16px; left: 50%; transform: translateX(-50%);
  width: calc(100% - 32px); max-width: 860px;
  display: flex; align-items: center; gap: 18px; height: 52px; padding: 0 14px 0 20px; border-radius: 16px;
  background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.18);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 14px 40px rgba(0,0,0,.3); color: #fff;
  transition: max-width .35s ease, top .35s ease, background .35s ease, box-shadow .35s ease, border-radius .35s ease;
}
.hpf-head.is-stuck { max-width: 540px; top: 10px; background: rgba(40,28,16,.85); border-radius: 999px; box-shadow: 0 10px 30px rgba(0,0,0,.45); }
.hpf-logo { font-size: 17px; font-weight: 800; color: #fff; text-decoration: none; }
.hpf-nav { display: flex; gap: 2px; margin-left: auto; }
.hpf-nav a { color: rgba(255,255,255,.88); text-decoration: none; font-size: 13px; font-weight: 600; padding: 7px 12px; border-radius: 999px; transition: background .2s ease; }
.hpf-nav a:hover { background: rgba(255,255,255,.16); }
.hpf-cta { font: inherit; font-size: 12.5px; font-weight: 700; color: #17110a; background: #e0a458; border: none; padding: 9px 16px; border-radius: 999px; cursor: pointer; transition: transform .15s ease; }
.hpf-cta:hover { transform: translateY(-1px); }

.hpf-scroll { height: 100%; overflow-y: auto; scrollbar-width: thin; }
.hpf-hero { min-height: 300px; display: grid; place-content: center; text-align: center; color: #fff; padding: 96px 24px 40px; background: radial-gradient(120% 120% at 50% 0%, #5a3a1c 0%, #17110a 70%); }
.hpf-hero h1 { margin: 0; font-size: 30px; font-weight: 800; font-family: "Hiragino Mincho ProN", serif; }
.hpf-hero p { margin: 12px 0 0; font-size: 14px; opacity: .82; }
.hpf-body { background: #f7f2e9; color: #4a3320; padding: 30px 26px 80px; line-height: 1.85; }
.hpf-body p { max-width: 560px; margin: 0 auto 18px; }

@media (prefers-reduced-motion: reduce) { .hpf-head, .hpf-cta { transition: none; } }
JavaScript
// (デモと同じフックを流用)スクロールでピル型ヘッダーを締める
(() => {
  const sc = document.getElementById('hpfScroll');
  const head = document.getElementById('hpfHead');
  if (!sc || !head) return;
  const apply = () => head.classList.toggle('is-stuck', sc.scrollTop > 40);
  let ticking = false;
  sc.addEventListener('scroll', () => { if (ticking) return; ticking = true; requestAnimationFrame(() => { apply(); ticking = false; }); }, { passive: true });
  apply();
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  let auto = !reduce, dir = 1;
  ['wheel', 'touchstart', 'pointerdown'].forEach(ev => sc.addEventListener(ev, () => { auto = false; }, { passive: true }));
  if (auto) {
    setTimeout(function step() {
      if (!auto) return;
      sc.scrollTop += dir * 1.6;
      if (sc.scrollTop >= 170) dir = -1; else if (sc.scrollTop <= 0) dir = 1;
      requestAnimationFrame(step);
    }, 900);
  }
})();

実装ガイド

使いどころ

モダンなブランドサイトやポートフォリオに。画面上端から浮かせた角丸+影のカプセル型ヘッダーで、スクロールすると幅が締まって中央に寄ります。

実装時の注意点

常に中央配置(left:50%+translateX(-50%))で、is-stuck 時に max-width と top、背景・角丸・影をまとめて切り替えます。位置を transform 固定にしているため幅アニメーションが滑らかです。

対応ブラウザ

backdrop-filter(-webkit- 併記)・transform・transition は全モダンブラウザ対応。未対応環境でも半透明背景で成立します。

よくある失敗

浮かせる分、ヒーロー側に上部余白を確保しないと内容と重なります。幅可変は max-width で行い、left/right を直接アニメーションしない方が滑らか。モバイルでは浮遊幅を画面幅に近づけ、はみ出しを防ぎます。

応用例

スクロールで透明→ソリッド、ナビをアイコン化、中央にロゴを残して両脇を畳む、影の強さをスクロール量に連動させるなどの展開ができます。

コード

HTML
<!-- 画面から浮いた角丸ピル型ヘッダー(スクロールで締まる) -->
<div class="hpf-frame">
  <header class="hpf-head" id="hpfHead">
    <a class="hpf-logo" href="#" onclick="return false">◉ Orbit</a>
    <nav class="hpf-nav">
      <a href="#" onclick="return false">製品</a>
      <a href="#" onclick="return false">設計</a>
      <a href="#" onclick="return false">価格</a>
    </nav>
    <button class="hpf-cta" type="button">始める</button>
  </header>

  <div class="hpf-scroll" id="hpfScroll">
    <section class="hpf-hero">
      <h1>浮遊するピル型ヘッダー</h1>
      <p>上端から浮いた角丸ナビ。スクロールすると幅が締まって中央に寄ります。</p>
    </section>
    <section class="hpf-body">
      <p>ピル型ヘッダーは余白の中に浮くことで、軽やかでモダンな印象を与えます。近年のブランドサイトで人気の表現です。</p>
      <p>スクロール量が閾値を超えると <code>is-stuck</code> が付き、幅・位置・影がまとめて切り替わります。</p>
      <p>このデモは自動でゆっくり往復し、締まる→戻るの動きを実演します。</p>
    </section>
  </div>
</div>
CSS
* { box-sizing: border-box; }
body { margin: 0; font-family: "Segoe UI", system-ui, -apple-system, sans-serif; }

.hpf-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: #0c0f1a; }

/* 浮遊するピル型ヘッダー(常に中央、スクロールで幅が締まる) */
.hpf-head {
  position: absolute; z-index: 10; top: 16px; left: 50%; transform: translateX(-50%);
  width: calc(100% - 32px); max-width: 860px;
  display: flex; align-items: center; gap: 18px;
  height: 52px; padding: 0 14px 0 20px;
  border-radius: 16px;
  background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.16);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 14px 40px rgba(0,0,0,.3);
  color: #fff;
  transition: max-width .35s ease, top .35s ease, background .35s ease, box-shadow .35s ease, border-radius .35s ease;
}
.hpf-head.is-stuck {
  max-width: 540px; top: 10px;
  background: rgba(16,18,32,.82);
  border-radius: 999px;
  box-shadow: 0 10px 30px rgba(0,0,0,.45);
}
.hpf-logo { font-size: 17px; font-weight: 800; color: #fff; text-decoration: none; }
.hpf-nav { display: flex; gap: 2px; margin-left: auto; }
.hpf-nav a { color: rgba(255,255,255,.86); text-decoration: none; font-size: 13px; font-weight: 600; padding: 7px 12px; border-radius: 999px; transition: background .2s ease; }
.hpf-nav a:hover { background: rgba(255,255,255,.14); }
.hpf-cta { font: inherit; font-size: 12.5px; font-weight: 700; color: #0c0f1a; background: #fff; border: none; padding: 9px 16px; border-radius: 999px; cursor: pointer; transition: transform .15s ease; }
.hpf-cta:hover { transform: translateY(-1px); }

.hpf-scroll { height: 100%; overflow-y: auto; scrollbar-width: thin; }
.hpf-hero {
  min-height: 300px; display: grid; place-content: center; text-align: center; color: #fff; padding: 96px 24px 40px;
  background: radial-gradient(120% 120% at 50% 0%, #3b2f80 0%, #0c0f1a 70%);
}
.hpf-hero h1 { margin: 0; font-size: 30px; font-weight: 800; }
.hpf-hero p { margin: 12px 0 0; font-size: 14px; opacity: .82; }
.hpf-body { background: #f6f7fb; color: #232842; padding: 30px 26px 80px; line-height: 1.85; }
.hpf-body p { max-width: 560px; margin: 0 auto 18px; }
.hpf-body code { background: rgba(99,102,241,.12); color: #4f46e5; padding: 1px 6px; border-radius: 5px; font-size: .92em; }

@media (prefers-reduced-motion: reduce) { .hpf-head, .hpf-cta { transition: none; } }
JavaScript
// スクロールでピル型ヘッダーを締める(中央寄せ・幅縮小)
(() => {
  const sc = document.getElementById('hpfScroll');
  const head = document.getElementById('hpfHead');
  if (!sc || !head) return;
  const apply = () => head.classList.toggle('is-stuck', sc.scrollTop > 40);
  let ticking = false;
  sc.addEventListener('scroll', () => {
    if (ticking) return; ticking = true;
    requestAnimationFrame(() => { apply(); ticking = false; });
  }, { passive: true });
  apply();
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  let auto = !reduce, dir = 1;
  ['wheel', 'touchstart', 'pointerdown'].forEach(ev => sc.addEventListener(ev, () => { auto = false; }, { passive: true }));
  if (auto) {
    setTimeout(function step() {
      if (!auto) return;
      sc.scrollTop += dir * 1.6;
      if (sc.scrollTop >= 170) dir = -1; else if (sc.scrollTop <= 0) dir = 1;
      requestAnimationFrame(step);
    }, 900);
  }
})();

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

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

# 追加してほしい効果
浮遊ピル型ヘッダー(ヘッダー)
画面上端から少し浮かせた、角丸+影のカプセル状ヘッダー。スクロールすると幅が締まって中央に寄ります。モダンなブランドサイトやポートフォリオで人気の“浮いている”ナビです。

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

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- 画面から浮いた角丸ピル型ヘッダー(スクロールで締まる) -->
<div class="hpf-frame">
  <header class="hpf-head" id="hpfHead">
    <a class="hpf-logo" href="#" onclick="return false">◉ Orbit</a>
    <nav class="hpf-nav">
      <a href="#" onclick="return false">製品</a>
      <a href="#" onclick="return false">設計</a>
      <a href="#" onclick="return false">価格</a>
    </nav>
    <button class="hpf-cta" type="button">始める</button>
  </header>

  <div class="hpf-scroll" id="hpfScroll">
    <section class="hpf-hero">
      <h1>浮遊するピル型ヘッダー</h1>
      <p>上端から浮いた角丸ナビ。スクロールすると幅が締まって中央に寄ります。</p>
    </section>
    <section class="hpf-body">
      <p>ピル型ヘッダーは余白の中に浮くことで、軽やかでモダンな印象を与えます。近年のブランドサイトで人気の表現です。</p>
      <p>スクロール量が閾値を超えると <code>is-stuck</code> が付き、幅・位置・影がまとめて切り替わります。</p>
      <p>このデモは自動でゆっくり往復し、締まる→戻るの動きを実演します。</p>
    </section>
  </div>
</div>

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

.hpf-frame { position: relative; width: 100%; height: 380px; overflow: hidden; background: #0c0f1a; }

/* 浮遊するピル型ヘッダー(常に中央、スクロールで幅が締まる) */
.hpf-head {
  position: absolute; z-index: 10; top: 16px; left: 50%; transform: translateX(-50%);
  width: calc(100% - 32px); max-width: 860px;
  display: flex; align-items: center; gap: 18px;
  height: 52px; padding: 0 14px 0 20px;
  border-radius: 16px;
  background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.16);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 14px 40px rgba(0,0,0,.3);
  color: #fff;
  transition: max-width .35s ease, top .35s ease, background .35s ease, box-shadow .35s ease, border-radius .35s ease;
}
.hpf-head.is-stuck {
  max-width: 540px; top: 10px;
  background: rgba(16,18,32,.82);
  border-radius: 999px;
  box-shadow: 0 10px 30px rgba(0,0,0,.45);
}
.hpf-logo { font-size: 17px; font-weight: 800; color: #fff; text-decoration: none; }
.hpf-nav { display: flex; gap: 2px; margin-left: auto; }
.hpf-nav a { color: rgba(255,255,255,.86); text-decoration: none; font-size: 13px; font-weight: 600; padding: 7px 12px; border-radius: 999px; transition: background .2s ease; }
.hpf-nav a:hover { background: rgba(255,255,255,.14); }
.hpf-cta { font: inherit; font-size: 12.5px; font-weight: 700; color: #0c0f1a; background: #fff; border: none; padding: 9px 16px; border-radius: 999px; cursor: pointer; transition: transform .15s ease; }
.hpf-cta:hover { transform: translateY(-1px); }

.hpf-scroll { height: 100%; overflow-y: auto; scrollbar-width: thin; }
.hpf-hero {
  min-height: 300px; display: grid; place-content: center; text-align: center; color: #fff; padding: 96px 24px 40px;
  background: radial-gradient(120% 120% at 50% 0%, #3b2f80 0%, #0c0f1a 70%);
}
.hpf-hero h1 { margin: 0; font-size: 30px; font-weight: 800; }
.hpf-hero p { margin: 12px 0 0; font-size: 14px; opacity: .82; }
.hpf-body { background: #f6f7fb; color: #232842; padding: 30px 26px 80px; line-height: 1.85; }
.hpf-body p { max-width: 560px; margin: 0 auto 18px; }
.hpf-body code { background: rgba(99,102,241,.12); color: #4f46e5; padding: 1px 6px; border-radius: 5px; font-size: .92em; }

@media (prefers-reduced-motion: reduce) { .hpf-head, .hpf-cta { transition: none; } }

【JavaScript】
// スクロールでピル型ヘッダーを締める(中央寄せ・幅縮小)
(() => {
  const sc = document.getElementById('hpfScroll');
  const head = document.getElementById('hpfHead');
  if (!sc || !head) return;
  const apply = () => head.classList.toggle('is-stuck', sc.scrollTop > 40);
  let ticking = false;
  sc.addEventListener('scroll', () => {
    if (ticking) return; ticking = true;
    requestAnimationFrame(() => { apply(); ticking = false; });
  }, { passive: true });
  apply();
  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
  let auto = !reduce, dir = 1;
  ['wheel', 'touchstart', 'pointerdown'].forEach(ev => sc.addEventListener(ev, () => { auto = false; }, { passive: true }));
  if (auto) {
    setTimeout(function step() {
      if (!auto) return;
      sc.scrollTop += dir * 1.6;
      if (sc.scrollTop >= 170) dir = -1; else if (sc.scrollTop <= 0) dir = 1;
      requestAnimationFrame(step);
    }, 900);
  }
})();

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

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