ページ内リンク『他のページから遷移するとズレる』という問題について
他のページからアンカーリンク(#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の値を調整してください。

