制作Note

ページ内リンク『他のページから遷移するとズレる』という問題について

他のページからアンカーリンク(#section1など)付きのURLに遷移したとき、目的の位置にピッタリ移動せず、微妙にズレてしまうことがあります。

これは、ブラウザがページを完全に読み込む前にスクロール位置を計算してしまうことが原因です。画像の読み込みやCSSの適用が完了する前に移動するため、最終的な表示位置がズレてしまうのです。



            

解決策のコード

 
window.addEventListener('load', function() {
  if (window.location.hash) {
    var target = document.querySelector(window.location.hash);
    if (target) {
      // まず一番上に戻す(一瞬で)
      window.scrollTo(0, 0);
      
      // 少し待ってからスムーズにスクロール
      setTimeout(function() {
        var headerHeight = 10;
        var targetPosition = target.getBoundingClientRect().top + window.scrollY - headerHeight;
        window.scrollTo({
          top: targetPosition,
          behavior: 'smooth'
        });
      }, 300);
    }
  }
});

コードの解説

1. ページ完全読み込み後に実行

window.addEventListener('load', function() {

loadイベントを使用することで、画像やCSS、フォントなど、すべてのリソースが読み込まれた後に処理を実行します。DOMContentLoadedではなくloadを使う点がポイントです。

2. ハッシュの存在確認

if (window.location.hash) {
  var target = document.querySelector(window.location.hash);
URLに#が含まれているか確認し、対応する要素を取得します。ハッシュがない通常のページ遷移では何も実行されません。

3. 一度トップに戻す

window.scrollTo(0, 0);
ブラウザが中途半端な位置にスクロールしている状態をリセットします。この処理は一瞬で行われるため、ユーザーにはほとんど気づかれません。

4. 少し待ってから正確な位置へスクロール

setTimeout(function() {
  var headerHeight = 10;
  var targetPosition = target.getBoundingClientRect().top + window.scrollY - headerHeight;
  window.scrollTo({
    top: targetPosition,
    behavior: 'smooth'
  });
}, 300);

300ミリ秒待つことで、レイアウトが完全に確定した状態で位置を計算できます。behavior: ‘smooth’により、スムーズなスクロールアニメーションで目的地に移動します。

カスタマイズのポイント

項目 変数 説明
ヘッダーの高さ headerHeight 固定ヘッダーがある場合は、その高さを指定
待機時間 setTimeoutの第2引数 重いページは長めに設定(300〜500ms推奨)

まとめ

このスクリプトを導入することで、どのページから遷移しても、アンカーリンクが正確な位置に移動するようになります。固定ヘッダーがあるサイトでは、headerHeightの値を調整してください。