【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に#~が含まれていた時
参考サイトメモ
旨く行きませんでしたが、以下のページにあるソースも気になりました。