【JS】アンカーへの画面遷移時に表示位置がズレてしまうときの対策
目次
アンカーポイントがずれてしまう
ハッシュタグを使用してアンカーの位置にジャンプしようとしたとき、LazyloadやSlick.jsなどのSliderを使っているせいか、画像表示ページが伸縮するために、意図する位置で表示されないことが起こりました。
具体的には画像スライダーのあるページに<form>でお問合せフォームを設置していて、actionには自らのページにハッシュタグを付けており、submitで送信後に戻ってきたときにスクロール位置がずれました。しかも、パソコンとスマホ(iPhone)で停まる位置が異なり、ブラウザを変えてもの同じ挙動でした。そこで、以下のソースで解決できました。jQueryが必要です。
解決できたソース
URLに#contactなどハッシュタグが含まれていた場合、ページ上部からアンカーまでの位置を取得し、数秒後に画面が伸縮した後に再度、アンカーのポジションを確認して比較します。もし、比較して変化があればその位置に画面をスクロールさせます。
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
//
//Lazyloadなどでアンカーの高さが変化する場合の対応
//
$(window).ready(function() {
try {
const deleyTime = 600; //アンカー位置を再確認するまでの待機時間(ミリ秒)
const adjust = 50; //高さの微調整
//URLに#タグがあるか確認
const getHash = ($this) => {
if (!location.hash){
console.log('アンカータグは指定されていません。');
} else {
return location.hash;
}
}
console.log('アンカータグは '+getHash()+' です。');
//アンカーの位置確認(1回目)
const firstPositionY = $(getHash()).offset().top;
console.log('最初に取得した '+getHash()+' の高さは '+firstPositionY+' です。');
//アンカーの位置確認(2回目)
const secondPositionY = ($this) => {
return $(getHash()).offset().top;
}
//数秒後にアンカーの位置が変わっていたら正しい位置にスクロール
setTimeout(function(){
console.log(deleyTime/1000+'秒後の '+getHash()+' の高さは '+secondPositionY()+' です。');
if(firstPositionY != secondPositionY()){
$('html,body').animate({ scrollTop: secondPositionY()+adjust }, 'fast');
console.log(getHash()+' の現在位置が変化しているため正しい位置にスクロールしました。')
}else{
console.log(getHash()+' の現在位置に変化はありません。')
}
}
,deleyTime);
} catch (error) {
console.log('アンカータグが見当たらないため処理を終了しました。');
}
});
</script>
以下の部分の最後にある'fast'を'slow'や'nomal'にするとスクロールのスピードが変わります。
$('html,body').animate({ scrollTop: secondPositionY()+adjust }, 'fast');
コンソールでログを確認
上記にソースにあるconsole.logで指定した文字列はブラウザのコンソール画面に出力され、処理の経過状態を確認することができます。以下の画面はEdgeですが、Chromiumベースのブラウザなら、F12を押すことでこの画面を出すことができます。
URLに#~が含まれていなかった時

URLに#~が含まれていた時

参考サイトメモ
旨く行きませんでしたが、以下のページにあるソースも気になりました。

