固定配置ヘッダー(フワッと表示)実装解説|JS & CSS Scroll Header Guide

デモで学ぶ JavaScript スクロール追従ヘッダー

スクロールに反応して現れる追従ヘッダーを、JavaScript と CSS の組み合わせで実装する方法をまとめたページ。出現のしかた・ヘッダーの縮小・背景の切り替え・IntersectionObserver 版まで、コピーしてすぐに使えるHTML・CSS・JSのコードを掲載しています。
HTML・CSS・JSコードプレビューツール にて実装確認ができます。

① スクロール量で出現させる — しきい値で判定する

LOGO
HomeAboutContact
LOGO
HomeAboutContact

ここから記事本文です。下へスクロールしてみてください。

ページの先頭には、ロゴとメニューを並べた大きめのヘッダーを置くのが一般的です。

ただし、そのヘッダーはスクロールすると画面の外へ流れていってしまいます。

読者が記事の途中でメニューを開きたくなったとき、わざわざ先頭まで戻るのは手間です。

そこで、スクロールが一定量を超えたタイミングで、もう一枚のヘッダーを画面上部に出します。

この2枚目が「追従ヘッダー」です。position: fixed で画面に貼り付けておきます。

初期状態では translateY(-100%) で上に逃がし、opacity: 0 で透明にしておきます。

JavaScript は、スクロール量がしきい値を超えたかどうかだけを見ています。

超えていればクラスを付け、戻れば外す。表示の切り替え自体は CSS の仕事です。

しきい値を「最初のヘッダーの高さ」にすると、入れ替わるように見えて自然です。

「100px」のような固定値にすると、ヘッダーの高さを変えても書き直さずに済みます。

「0px」にすると、少しでも動いた瞬間に追従ヘッダーが出てきます。

上のボタンでしきい値を切り替えると、出現するタイミングが変わるのが分かります。

どれが正解ということはなく、サイトの見せ方に合わせて選んでください。

迷ったら、最初のヘッダーの高さを使う方式がもっとも違和感が少ないはずです。

アニメーションの時間は 0.2〜0.3 秒あたりが、速すぎず遅すぎずで扱いやすい範囲です。

ここが最後の行です。上へ戻ると追従ヘッダーが消えます。

現在: しきい値 ヘッダーの高さ(56px) — 追従ヘッダー非表示

HTML
<header class="hero-header">
  <span class="logo">LOGO</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<header class="follow-header">
  <span class="logo">LOGO</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<main>
  <p>ページの内容</p>
</main>
CSS
.hero-header,
.follow-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  padding: 0 16px;
  box-sizing: border-box;
  background: #1e293b;
}

.logo {
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
}

.nav {
  display: flex;
  gap: 16px;
}

.nav a {
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.8rem;
  text-decoration: none;
}

.follow-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  transform: translateY(-100%);
  opacity: 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.follow-header.is-shown {
  transform: translateY(0);
  opacity: 1;
}
JS
document.addEventListener('DOMContentLoaded', function () {
  var follow = document.querySelector('.follow-header');
  var showPoint = document.querySelector('.hero-header').offsetHeight;

  window.addEventListener('scroll', function () {
    var pos = window.scrollY || document.documentElement.scrollTop;
    if (pos > showPoint) {
      follow.className = 'follow-header is-shown';
    } else {
      follow.className = 'follow-header';
    }
  }, { passive: true });
});
CSS — transform + opacity + transition

追従ヘッダーは最初から HTML に置いておき、CSS で見えない状態にしておきます。translateY(-100%) で自分の高さぶんだけ上へ逃がし、opacity: 0 で透明にする。この2つに transition を指定しておけば、クラスが付いた瞬間に0.3秒かけて滑り降りてきます。display: none で消してしまうとアニメーションが効かないので、必ず transform か opacity で隠してください。

JavaScript — しきい値と比較してクラスを付け外しするだけ

JavaScript の仕事は「今どこまでスクロールしたか」を取り出して、しきい値と比べることだけです。window.scrollY で取得した値がしきい値を超えていれば is-shown クラスを付け、下回れば外します。見た目の変化はすべて CSS 側が担当するので、JavaScript から style を直接書き換える必要はありません。この分担にしておくと、あとからデザインを変えたくなっても CSS だけ直せば済みます。

デモの表示について

position: fixed は画面(ビューポート)を基準に配置されるため、記事内に埋め込んだ枠の中では再現できません。上のデモは枠内スクロールで同じ見え方になるよう position: sticky で作っていますが、コピペ用コードは実際のページでそのまま使える position: fixed 版です。

② 下へ進むと隠し、上へ戻すと出す — スクロール方向で判定する

LOGO
HomeAboutContact
LOGO
HomeAboutContact

下へ少し進んでから、上へ戻してみてください。

読み進めている最中は、画面を広く使いたいものです。

そこで「下へ進んでいるあいだはヘッダーを隠す」という考え方が出てきます。

逆に、上へ戻す動きは「何かを探している」というサインだと解釈できます。

このときにヘッダーを出せば、メニューへすぐ手が届きます。

ニュースサイトやブログでよく見かける挙動が、まさにこれです。

実装は、前回のスクロール位置を変数に覚えておくだけで済みます。

今回の位置が前回より大きければ下方向、小さければ上方向です。

比較したあとに、変数を今回の値で上書きするのを忘れないでください。

ここで注意したいのが、ごくわずかな揺れでも方向判定が反応してしまう点です。

スマートフォンの慣性スクロールでは、1pxだけ戻るような動きが頻繁に起きます。

そのままだとヘッダーが出たり消えたりを繰り返し、かなり目障りになります。

対策は簡単で、4px程度の「あそび」を設けて、それ以下の変化は無視します。

コード内の lastPos + 4 と lastPos – 4 がその判定です。

もうひとつ、ページ最上部では追従ヘッダーを隠しておくのが自然です。

最上部には元のヘッダーがあるので、2枚重なって見えてしまうためです。

右のボタンで「しきい値だけ」に切り替えると、①と同じ動きに戻ります。

ここが最後の行です。ゆっくり上へ戻してみてください。

現在: 方向で判定 — 最上部のため非表示

HTML
<header class="hero-header">
  <span class="logo">LOGO</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<header class="follow-header">
  <span class="logo">LOGO</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<main>
  <p>ページの内容</p>
</main>
CSS
.hero-header,
.follow-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  padding: 0 16px;
  box-sizing: border-box;
  background: #1e293b;
}

.logo {
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
}

.nav {
  display: flex;
  gap: 16px;
}

.nav a {
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.8rem;
  text-decoration: none;
}

.follow-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  transform: translateY(-100%);
  opacity: 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.follow-header.is-shown {
  transform: translateY(0);
  opacity: 1;
}
JS
document.addEventListener('DOMContentLoaded', function () {
  var follow = document.querySelector('.follow-header');
  var heroHeight = document.querySelector('.hero-header').offsetHeight;
  var lastPos = 0;

  window.addEventListener('scroll', function () {
    var pos = window.scrollY || document.documentElement.scrollTop;

    if (pos <= heroHeight) {
      follow.className = 'follow-header';
    } else if (pos > lastPos + 4) {
      follow.className = 'follow-header';
    } else if (pos < lastPos - 4) {
      follow.className = 'follow-header is-shown';
    }

    lastPos = pos;
  }, { passive: true });
});
lastPos — 前回のスクロール位置を覚えておく

スクロールの方向は、単体の値からは分かりません。前回の位置を変数に保存しておき、今回の値と比べてはじめて「増えた(下へ)」「減った(上へ)」が判定できます。処理の最後に lastPos = pos で必ず上書きしてください。ここを書き忘れると、常に「先頭からどれだけ動いたか」を比べることになり、ページの途中で方向判定が固まってしまいます。

+4 / -4 — わずかなあそびで、ちらつきを防ぐ

スマートフォンの慣性スクロールやトラックパッドの操作では、下へ動いている最中でも1pxだけ戻るような揺れが頻繁に発生します。差が0より大きいかどうかで判定すると、この揺れを毎回「上へ戻った」と解釈してしまい、ヘッダーが激しく点滅します。4px程度のあそびを設けて、それ以下の変化は無視するのが実用的です。数値を大きくするほど反応が鈍く、安定した動きになります。

最上部では隠す — 元のヘッダーとの二重表示を避ける

ページ最上部にはもともとのヘッダーが表示されています。この位置で追従ヘッダーまで出してしまうと、同じメニューが2段に重なって見えてしまいます。最初の条件 pos <= heroHeight で「元のヘッダーがまだ見えている範囲では隠す」と決めておくと、入れ替わるように自然につながります。

③ スクロールでヘッダーを縮める — コンパクト表示に切り替える

BRAND
HomeAboutContact

下へスクロールすると、ヘッダーの見た目が変わります。

ページの先頭では、ロゴを大きく見せてブランドの印象を残したい。

けれども読み始めたあとは、ヘッダーが縦幅を取りすぎるのは邪魔になります。

この2つを両立させるのが、スクロールに応じてヘッダーを縮める手法です。

やることは、①や②とまったく同じで、クラスを付け外しするだけです。

違うのは、隠すのではなく高さや文字サイズを変える点だけです。

高さに transition を効かせておけば、ぬるっと縮んでいくように見えます。

ロゴの font-size にも transition を付けると、一緒に小さくなって自然です。

注意点は、高さを変えるとページ全体のレイアウトが動くことです。

ヘッダーが sticky の場合は下のコンテンツが上下にずれるので、変化量は控えめにします。

76px から 48px 程度なら、違和感が出にくい範囲です。

もうひとつのやり方が、右のボタンで試せる「影だけ付ける」パターンです。

高さは変えず、スクロール後に box-shadow を足してヘッダーを浮かせます。

レイアウトがまったく動かないので、もっとも安全な選択肢と言えます。

コンテンツとヘッダーの境目をはっきりさせたいだけなら、こちらで十分です。

どちらの場合も、transition を入れ忘れるとカクッと切り替わってしまいます。

ここが最後の行です。上へ戻すと元の大きさに戻ります。

現在: 高さ 76px(通常表示)

HTML
<header class="site-header">
  <span class="logo">BRAND</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<main>
  <p>ページの内容</p>
</main>
CSS
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 76px;
  padding: 0 16px;
  box-sizing: border-box;
  background: #1e293b;
  transition: height 0.25s ease, box-shadow 0.25s ease;
}

.site-header .logo {
  color: #fff;
  font-weight: 700;
  font-size: 1.15rem;
  transition: font-size 0.25s ease;
}

.nav {
  display: flex;
  gap: 16px;
}

.nav a {
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.8rem;
  text-decoration: none;
}

.site-header.is-compact {
  height: 48px;
}

.site-header.is-compact .logo {
  font-size: 0.85rem;
}
JS
document.addEventListener('DOMContentLoaded', function () {
  var header = document.querySelector('.site-header');

  window.addEventListener('scroll', function () {
    var pos = window.scrollY || document.documentElement.scrollTop;
    if (pos > 60) {
      header.className = 'site-header is-compact';
    } else {
      header.className = 'site-header';
    }
  }, { passive: true });
});
transition — 変化させたいプロパティを個別に指定する

transition: height 0.25s ease のように、アニメーションさせたいプロパティを名指しします。transition: all と書くこともできますが、意図しないプロパティまで滑らかに変化してしまい、動きが重くなる原因になります。複数指定したいときは transition: height 0.25s ease, box-shadow 0.25s ease のようにカンマで並べてください。ロゴを一緒に縮めたい場合は、ロゴ側にも別途 transition が必要です。

高さを変える場合はレイアウトのずれに注意

ヘッダーの高さが変わると、その下にあるコンテンツの位置も動きます。sticky や通常フローのヘッダーではこのずれが目に見えるため、変化量は控えめにしてください。76px から 48px 程度なら違和感が出にくい範囲です。レイアウトをまったく動かしたくない場合は、右のボタンで試せる「影だけ付ける」パターンが安全です。高さは固定のまま box-shadow だけを足して、ヘッダーが浮いているように見せます。

④ 背景を透明から不透明へ — メインビジュアルに重ねる

LOGO
HomeAboutContact
MAIN VISUAL

下へスクロールすると、ヘッダーに背景が付きます。

大きな写真やグラデーションをページ最上部に置くデザインはよく使われます。

このとき、ヘッダーの背景を塗ってしまうとビジュアルが分断されてしまいます。

そこで、最上部ではヘッダーを透明にして、写真の上に文字だけを浮かせます。

ただし、そのままスクロールすると本文とヘッダーの文字が重なって読めなくなります。

ビジュアルを抜けたところで背景を付ければ、この問題は解決します。

切り替えのタイミングは「ビジュアルの高さ – ヘッダーの高さ」を超えたときです。

この式にしておくと、ヘッダーの下端がビジュアルの下端に達した瞬間に切り替わります。

background に transition を効かせておけば、じわっと色が乗るように見えます。

右のボタンでは、単色ではなく backdrop-filter を使う方法を試せます。

半透明の背景色と blur を組み合わせると、すりガラスのような質感になります。

背後のコンテンツがぼんやり透けるので、写真の多いサイトと相性が良い表現です。

ただし backdrop-filter は描画の負荷が高めなので、多用は避けたほうが無難です。

透明なヘッダーの上に置く文字は、白か明るい色にして読みやすさを確保してください。

写真によっては、文字の下に薄いグラデーションを敷くと安定します。

ここが最後の行です。上へ戻すと背景が消えます。

現在: 背景 透明(メインビジュアルの上)

HTML
<header class="site-header">
  <span class="logo">LOGO</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<div class="hero">MAIN VISUAL</div>

<main>
  <p>ページの内容</p>
</main>
CSS
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  padding: 0 16px;
  box-sizing: border-box;
  background: transparent;
  transition: background 0.3s ease, box-shadow 0.3s ease;
}

.logo {
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
}

.nav {
  display: flex;
  gap: 16px;
}

.nav a {
  color: rgba(255, 255, 255, 0.9);
  font-size: 0.8rem;
  text-decoration: none;
}

.hero {
  height: 320px;
  background: linear-gradient(135deg, #6366f1, #a855f7);
}

.site-header.is-solid {
  background: #1e293b;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}
JS
document.addEventListener('DOMContentLoaded', function () {
  var header = document.querySelector('.site-header');
  var hero = document.querySelector('.hero');
  var showPoint = hero.offsetHeight - header.offsetHeight;

  window.addEventListener('scroll', function () {
    var pos = window.scrollY || document.documentElement.scrollTop;
    if (pos > showPoint) {
      header.className = 'site-header is-solid';
    } else {
      header.className = 'site-header';
    }
  }, { passive: true });
});
切り替え位置 — ビジュアルの高さからヘッダーの高さを引く

しきい値を hero.offsetHeight – header.offsetHeight にしておくと、ヘッダーの下端がちょうどビジュアルの下端に届いた瞬間に背景が付きます。単純にビジュアルの高さだけを使うと、切り替わるのがヘッダー1枚ぶん遅れてしまい、一瞬だけ本文の上に透明なヘッダーが乗る状態が生まれます。数値を直接書かずに offsetHeight から計算しておけば、あとでビジュアルの高さを変えても直す必要がありません。

backdrop-filter — すりガラス風の背景にする

単色で塗るかわりに、半透明の背景色と backdrop-filter: blur() を組み合わせると、背後のコンテンツがぼやけて透ける表現になります。background: rgba(15, 23, 42, 0.55) と backdrop-filter: blur(10px) のように、必ず半透明の背景色とセットで指定してください。背景色が完全に不透明だとぼかす対象が隠れてしまい、効果が見えません。描画の負荷は高めなので、画面内に何枚も重ねるのは避けてください。

⑤ scroll イベントを使わない — IntersectionObserver で判定する

LOGO
HomeAboutContact
LOGO
HomeAboutContact

紫の線を通過したところで追従ヘッダーが出ます。

ここまでは、どちらのボタンを選んでも同じ位置で切り替わります。

監視ポイント

違うのは、その判定を何が担当しているかです。

scroll イベント版は、スクロールのたびに現在位置を取り出して比較しています。

つまり、指を動かしているあいだじゅう、ずっと処理が走り続けます。

IntersectionObserver 版は、監視したい要素をブラウザに登録しておくだけです。

その要素が画面に入った・出たタイミングだけ、ブラウザから通知が届きます。

通過していない間はこちらの処理は一切走らないので、無駄がありません。

判定はブラウザ側で行われるため、スクロール中の描画も詰まりにくくなります。

コードの見た目も、しきい値を計算する必要がないぶん素直になります。

使い方は、通知を受け取る関数を渡して new し、observe() で要素を登録するだけです。

通知には isIntersecting という真偽値が入っていて、画面内かどうかが分かります。

ただし「画面外」には上に抜けた場合と下にある場合の両方が含まれます。

そこで boundingClientRect.top を見て、上へ抜けたときだけ表示する形にします。

observe() を呼んだ直後にも一度通知が届くので、初期状態も自動で決まります。

要素の位置が変わっても勝手に追従するため、レイアウト変更にも強い書き方です。

迷ったら、まずは scroll イベント版で作り、必要になったら移行すれば十分です。

ここが最後の行です。上へ戻すと追従ヘッダーが消えます。

現在: scroll イベントで判定中 — 追従ヘッダー非表示

HTML
<header class="hero-header">
  <span class="logo">LOGO</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<header class="follow-header">
  <span class="logo">LOGO</span>
  <nav class="nav">
    <a href="#">Home</a>
    <a href="#">About</a>
    <a href="#">Contact</a>
  </nav>
</header>

<div class="watch-point"></div>

<main>
  <p>ページの内容</p>
</main>
CSS
.hero-header,
.follow-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 56px;
  padding: 0 16px;
  box-sizing: border-box;
  background: #1e293b;
}

.logo {
  color: #fff;
  font-weight: 700;
  font-size: 0.9rem;
}

.nav {
  display: flex;
  gap: 16px;
}

.nav a {
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.8rem;
  text-decoration: none;
}

.follow-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  transform: translateY(-100%);
  opacity: 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.follow-header.is-shown {
  transform: translateY(0);
  opacity: 1;
}

.watch-point {
  height: 1px;
}
JS
document.addEventListener('DOMContentLoaded', function () {
  var follow = document.querySelector('.follow-header');
  var mark = document.querySelector('.watch-point');
  var showPoint = mark.offsetTop;

  window.addEventListener('scroll', function () {
    var pos = window.scrollY || document.documentElement.scrollTop;
    if (pos > showPoint) {
      follow.className = 'follow-header is-shown';
    } else {
      follow.className = 'follow-header';
    }
  }, { passive: true });
});
IntersectionObserver — 監視したい要素をブラウザに預ける

new IntersectionObserver() に通知を受け取る関数を渡し、observe() で監視対象の要素を登録します。あとは、その要素が画面に入った・出たタイミングだけブラウザから通知が届きます。スクロールのたびに位置を計算する必要がなく、判定はブラウザ側で処理されるため、スクロール中の描画が詰まりにくくなります。監視をやめたいときは disconnect() を呼びます。

isIntersecting だけでは足りない理由

isIntersecting が false になるのは「監視要素が画面外にある」ときですが、これには上へ抜けた場合と、まだ下にあって画面に入っていない場合の両方が含まれます。ページ読み込み直後は後者なので、false だけを頼りにすると最初からヘッダーが出てしまいます。boundingClientRect.top が0より小さいかどうかを併せて見て、上へ抜けたときだけ表示するようにしてください。

デモの表示について

上のデモは記事内の枠でスクロールを再現しているため、IntersectionObserver に root オプションでその枠を指定しています。実際のページでは画面全体が基準になるので、root の指定は不要です。コピペ用コードは実ページ向けの scroll イベント版で、ボタンを IntersectionObserver 側へ切り替えると同じ動きを IntersectionObserver で書いたコードに差し替わります。

scroll イベントは高い頻度で走ります。ハンドラの中で重い処理をすると、スクロールがカクついて体感品質が一気に落ちます。addEventListener の第3引数に { passive: true } を渡すと「この処理は preventDefault() を呼ばない」とブラウザに伝えられ、スクロールを待たせずに描画を進められます。さらに、クラスの付け外し以上のことをする場合は requestAnimationFrame でまとめてから実行すると安定します。ハンドラの中で offsetHeight や getBoundingClientRect() を毎回読むのは特に重いので、変わらない値は最初に一度だけ取得しておいてください。

JavaScript を使わず CSS だけで固定ヘッダーは作れますか?

「常に画面上部に残す」だけなら position: fixedposition: sticky で足ります。JavaScript が必要になるのは、このページのように「スクロール量や方向に応じて見た目を変えたい」場合です。ヘッダーをただ固定したいだけなら、まずは CSS だけの方法から試してください。CSS だけで作る固定ヘッダーの実装解説はこちら

スクロールしても追従ヘッダーが出てきません。

よくある原因は3つです。1つ目は、要素の取得に失敗しているケース。<script><head> に置いていると HTML より先に実行されるため、DOMContentLoaded で囲むか、</body> の直前に置いてください。2つ目は、スクロールしているのが window ではなく特定の要素だというケース。overflow: auto を指定した要素の中をスクロールしている場合、イベントは window ではなくその要素に付ける必要があります。3つ目は、祖先要素に transformfilterbackdrop-filter が指定されているケースで、この場合 position: fixed の基準が画面ではなくその祖先に変わってしまいます。

scroll イベントは負荷が高いと聞きました。対策は必要ですか?

クラスを付け外しするだけなら、そのままでも問題になることはほとんどありません。まず入れておきたいのは { passive: true } で、これは1行足すだけでスクロールの応答性が改善します。ハンドラの中で高さを測ったり、複数の要素を書き換えたりする場合は、requestAnimationFrame でまとめてから実行すると安定します。判定したいのが「特定の位置を通過したか」だけなら、⑤の IntersectionObserver に置き換えるのがもっとも軽い選択です。

追従ヘッダーの下にコンテンツが隠れてしまいます。

このページの構成では、最初のヘッダーが通常フローで場所を取っているため、追従ヘッダーが出ても本文が隠れることはありません。隠れるのは、ページ先頭から position: fixed のヘッダーだけを置いた場合です。その場合は本文側にヘッダーと同じ高さの padding-top を入れて逃がします。また、ページ内リンクで飛んだ先の見出しがヘッダーに隠れる問題は、リンク先の要素に scroll-margin-top を指定すると解決します。どちらも CSS 側の対処法としてこちらで解説しています

アニメーションが苦手なユーザーへの配慮は必要ですか?

動きの多い演出で気分が悪くなる人がいるため、OS 側で「視差効果を減らす」を有効にしているユーザーには動きを抑えるのが望ましいです。CSS の @media (prefers-reduced-motion: reduce) の中で transition: none を指定すれば、ヘッダーはアニメーションせず即座に切り替わります。表示・非表示の機能自体は残るので、使い勝手を損なわずに配慮できます。1ブロック足すだけなので、追従ヘッダーのように常に目に入る要素には入れておくことをおすすめします。


当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次