そんなことがあるのかな…?と思ったら、そんなことがありましたので記録として残しておきたいと思います…。
アンカー要素がfixedの場合にずれる?
アンカー要素の position
が fixed
の場合が考えられます。上部のヘッダーが固定されているため、スクロールに応じてアンカーの位置がズレてしまうことがあります。
あとは、Lazy Load(レイジーロード)/画像の遅延読み込みをしていることで、画像の表示が追いつかずにアンカーの位置がずれることも
position を relative に設定する
この問題を回避するには、アンカー要素の position
を relative
に設定するという方法が考えられます。アンカー要素は親要素を基準に相対的な位置を保つことができます。
また、アンカー要素の top
と left
プロパティを使用して、アンカー要素を移動させることもできます。これらのプロパティを使用することで、アンカー要素を移動させることができます。
# HTML
<div id="anchor">Anchor</div>
# CSS
#anchor {
position: relative;
top: 10px;
left: 10px;
}
アンカー要素の位置を固定する方法です。これらの方法を使用することで、画面移動時にアンカーの位置がズレる問題を回避することができます。
ただし、この方法だと、固定されているメニューの固定が解除されてしまいます。positionを変更せずに解決するには、JavaScriptで調整する方法があります。
解決できたソース(JavaScript)
試されている方も多くいらっしゃいましたが、まずアンカーの場所を取得して、その後に正しいアンカー位置に移動する、という方法です。
[rml_read_more]
<script>
$(window).ready(function() {
try {
const delayTime = 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(delayTime/1000+'秒後の '+getHash()+' の高さは '+secondPositionY()+' です。');
if(firstPositionY != secondPositionY()){
$('html,body').animate({ scrollTop: secondPositionY()+adjust }, 'fast');
console.log(getHash()+' の現在位置が変化しているため正しい位置にスクロールしました。')
}else{
console.log(getHash()+' の現在位置に変化はありません。')
}
}
,delayTime);
} catch (error) {
console.log('アンカータグが見当たらないため処理を終了しました。');
}
});
</script>
このJavaScriptコードは、URL内のアンカータグがページ上で位置を変更した場合に、自動的にスクロールの調整を行うものです。以下がこのコードが行うことです。
delayTime
という変数を設定します。これは、アンカー位置を再確認するまでの待機時間(ミリ秒)です。adjust
という変数を設定します。これは、高さの微調整値です。getHash
という関数を定義します。この関数は、現在のURLに#タグがあるかどうかを確認し、あれば#タグを返します。なければ、コンソールに「アンカータグは指定されていません。」と表示します。console.log
を使って、現在のURLの#タグを表示します。firstPositionY
という変数を設定します。これは、最初に取得した#タグの高さです。secondPositionY
という関数を定義します。この関数は、現在の#タグの高さを返します。setTimeout
を使って、一定時間後に現在の#タグの高さを再度取得します。その際、1回目に取得した高さと異なっていた場合には、正しい位置にスクロールするように処理を行います。スクロール処理には、jQueryのanimate
を使用しています。- 例外処理を追加し、#タグが見つからない場合には、コンソールに「アンカータグが見当たらないため処理を終了しました。」と表示します。
こんなことができるとは…素晴らしいですね…。
まとめ
対応してくださっている方々、本当にありがとうございます。
このコードは、ページが読み込まれたときにURLに含まれるアンカータグの位置を確認し、位置が変わった場合にはスクロールを調整する処理を行います。
もし目次リンクをクリックしてアンカータグに移動する際に同様の処理を行いたい場合は、別の方法が必要です。ご参考ください。