トラブルシュート

固定ヘッダーでスクロール位置がずれるときの原因と直し方

ページ内リンクやアンカーへスクロールしたとき、固定ヘッダーの高さ分だけ見出しが隠れてしまうのは古典的なCSSの問題です。しかし対処法を知らないままAIに生成させると同じバグが繰り返されます。この記事ではscroll-margin-topやJavaScriptでの補正など、状況別の解決策を解説します。

よくある原因

position: fixedで固定されたヘッダーはドキュメントフローから外れるため、アンカーリンクでスクロールしても対象要素の上端がヘッダーの裏に隠れます。例えばheight: 60pxの固定ヘッダーがある場合、`#section1`にリンクすると見出しが上60px分隠れて表示されます。

AIが生成するHTMLでは、固定ヘッダーのCSSは書かれてもアンカースクロールのオフセット処理が省略されることがほとんどです。デザイン的な指示として「ヘッダーを固定して」とだけ伝えると、scroll-margin-topやscrollToのoffset指定まで含めてくれないAIが大半です。

  • 相手がログインなしで開ける状態か確認する
  • PCとスマホで最低1回ずつ表示を確認する
  • 内部情報・個人情報・不要な外部送信が残っていないか見る
  • レビュー期限と修正時の差し替え方を決めておく

自分側で確認すること

最も簡単な修正はCSSでスクロール先の要素にscroll-margin-topを設定することです。固定ヘッダーが60pxなら、`h2, h3 { scroll-margin-top: 70px; }`と若干の余白を加えた値を指定します。この1行で追加JSなしに全見出しのアンカースクロール位置を補正できます。

scroll-margin-topはCSS Scroll Snap Moduleの一部で、Chrome/Firefox/Safariの主要ブラウザで2019年以降サポートされています。古いIE対応が不要なプロジェクトであれば最もシンプルな解決策です。DevToolsでElementsパネルを開き、対象要素にtemporarily add styleでscroll-margin-topを試して効果を確認してから本番に適用してください。

  • HTML内の外部script・form action・iframeを確認する
  • APIキーやトークンらしき文字列がないか検索する
  • 画像・CSS・JSのパスが公開後も解決できるか見る
  • noindexと認証を混同せず、必要なら両方設定する

相手側で確認すること

修正後のHTMLを共有したら、相手に「目次の各リンクをクリックしてそれぞれの見出しが正しく表示されるか確認してください」と具体的な操作手順を伝えてください。問題が解消されているかどうかを「スクロールした」という曖昧な表現ではなく、「見出しが隠れずに見えるか」という確認ポイントで依頼します。

相手が使うブラウザによっては動作が異なる場合があります。特にSafariとChromeでscroll-behaviorの扱いが違うため、smooth scrollを使っている場合はSafariで正しくオフセットされるかを確認してもらうと安心です。相手に「ChromeとSafariの両方で確認してほしい」と明示してください。

  • HTML内の外部script・form action・iframeを確認する
  • APIキーやトークンらしき文字列がないか検索する
  • 画像・CSS・JSのパスが公開後も解決できるか見る
  • noindexと認証を混同せず、必要なら両方設定する

再発防止の運用

HTMLテンプレートのCSSに最初から`[id] { scroll-margin-top: 80px; }`を含めておくことで、任意の要素へのアンカーリンクで常にオフセットが効くようになります。ヘッダー高さが変わってもCSS変数(--header-height)で一元管理すれば修正箇所が1箇所で済みます。

AIへの生成依頼時に「固定ヘッダーがある場合はscroll-margin-topでアンカースクロールのオフセットを設定すること」を明示的に指示に含めましょう。さらに生成後のレビューチェックリストに「固定ヘッダー + ページ内リンクの組み合わせがある場合はscroll-margin-topを確認」という項目を加えると再発防止になります。

  • HTML内の外部script・form action・iframeを確認する
  • APIキーやトークンらしき文字列がないか検索する
  • 画像・CSS・JSのパスが公開後も解決できるか見る
  • noindexと認証を混同せず、必要なら両方設定する

よくある質問

scroll-margin-topはCSSのどこに書けばよいですか?

アンカー先になるh2やh3、またはid属性を持つsection要素などに直接指定します。`h2 { scroll-margin-top: 80px; }`のようにセレクターでまとめて指定するのが効率的です。固定ヘッダーの高さより少し大きい値にしてください。

JavaScriptでスムーススクロールを実装している場合はCSSのscroll-margin-topは効きますか?

scrollIntoView()を使っている場合はscroll-margin-topが有効です。ただし独自のscrollToやoffsetTop計算でスクロールしている場合は、offsetTopにヘッダー高さを引いた値を手動で計算する実装が必要です。

SPAフレームワーク(React/Vue)でも同じCSSで対応できますか?

scroll-margin-topはフレームワーク非依存のCSSプロパティなので同様に使えます。ただしSPAはページ遷移時にスクロール位置がリセットされないケースがあるため、ルーター側でscrollBehaviorオプションを設定する対応も併用することをお勧めします。

関連記事

トラブルシュート

iPhoneだけ横スクロールするときの原因と直し方

iPhoneだけ横スクロールが発生するレイアウト崩れに困っているWeb制作者向けに、overflow・viewport・固定幅要素・margin負値の4パターンを診断・修正する手順をまとめた記事。

6分で読める
「トラブルシュート」の記事をもっと見る →