MENU

jqueryのスクロールでページ内リンクに推移させると位置がずれる問題の解決策

はてなブログの目次をjqueryで作って目次のリンクをクリックしたら、見出しの位置までスクロールさせる実装をさせていたのですが、なぜか見出しの中心までスクロールしてしまうので対策を考えました。

今回はjqueryでスクロールさせる場合ですね。

目次をクリックしたらその見出しまでスクロールさせるコード

$('.section-list a').on("click", function() {
    const target = $(this.hash); // 対応するセクションの要素を取得する
    const headerHeight = target.outerHeight() / 2; // セクションの高さの半分を取得する
    const topOffset = target.offset().top; // セクションの上端からの距離を取得する
    const scrollTo = topOffset - headerHeight; // スクロール位置を微調整する
    $('html,body').animate({
        scrollTop: scrollTo
    }, 50);
    return false;
});

コードレビュー

jqueryのoffset().topは指定された要素のドキュメント上の位置を返します。具体的には、指定された要素の上端が、ドキュメント上のどの位置にあるかを返すものですが、なぜか中心までスクロールしてしまいます。この原因はわからなかったのですが、見出し要素の中心までスクロールしてしまうのでこれを修正するために「見出しの高さ÷2」分を差し引くことで解決しました。

const headerHeight = target.outerHeight() / 2; ←これで見出しの高さ÷2 分の高さを取得 const scrollTo = topOffset - headerHeight; ← トップオフセットからさきほどのheaderHeightを引きます

$(this.hash)について

$(this.hash)はリンク先の要素を取得します。

たとえば

<h2 id="hoge">見出し</h2>

となっている場合はa要素は

<a href="#hoge">リンク</a>

の形になっている必要があります。

hashとは#です。#hogeハッシュの要素を取得するということですね。