よくこういう記事の目次とかページ内の見出しに飛ぶようなリンクありますよね?
こういうhrefに飛びたい位置の要素のid名を指定したリンクを「アンカーリンク」と呼ぶそうです。
ただこのリンク、ページ上部にfixedなどで固定したヘッダーがあるとうまく飛ばないことがよく起きます。
巷では、スムーススクロールと併せてjQueryで解決する例が溢れているので、今回はこれをJavaScriptで解決してみます。
JavaScriptを使わなくても解決できる
「今回はこれをJavaScriptで解決してみます。」と言いましたが、基本的にはJavaScriptを使わなくても解決できます。
padding-top: 50px;
margin-top: -50px;
これを飛びたい先の要素(見出しなど)に指定すればいいわけですが、デザインなどの都合でどうしてもこれを適用できないとか、CSS調整するのめんどくさい時とかあると思います。
そういう時にCSS・jQueryなしで使えるコードを作ってみました。
実際のコード
document.addEventListener('window.onload', () => {
let headH = document.getElementsByTagName('header')[0].offsetHeight + 10; //ヘッダーの高さを取得
mokujiLink(headH);
});
function mokujiLink(headH = 0) {
for (let i = 0; i < document.querySelectorAll('a[href^="#"]').length; i++) {
let lect = window.pageYOffset + document.getElementById(document.querySelectorAll('a[href^="#"]')[i].getAttribute("href").replace('#', '')).getBoundingClientRect().top - headH;
document.querySelectorAll('a[href^="#"]')[i].setAttribute("onClick", 'window.scrollTo(0,'+lect+')');
document.querySelectorAll('a[href^="#"]')[i].removeAttribute("href")
}
}
document.querySelectorAll('a[href^="#"]')
でページ内の全てのアンカーリンクを取得します。
飛ぶ位置を、ヘッダー要素の高さ分引いて調整することで被らないようにしています。
アンカーリンクの数だけfor文で「所定のid要素にscrollするonclick」をaddしているわけです。
シンプルですね。
ただ、TurbolinksやService Workerなど、ページの読み込みをXHRで行なっている場合は正しい動作をしないことがあるので、注意してください。
また、もっといいやり方があったら、ぜひコメント欄で教えてください。
ありがとうございました。