Bootstrap 5.2.0 sticky と scrollspy を同時に使う

アフィリエイト広告を利用しています

このページの内容が役に立ったら X (旧twitter) でフォローして頂けると励みになります
挨拶や報告は無しで大丈夫です

Bootstrap 5.2.0 を使って構築しているWebサイトで sticky と scrollspy を同時に使いたくなって困ったのでここに残しておきます。

sticky ってなんだ?

sticky とは、画面をスクロールしていったときに見出しタグが画面の上にへばりついてるのを見かけたことがありませんか?

現在の見出しブロックが分かる有りがたい機能です。

cssだと次のように書きます。

h2.sample {
  position : sticky;
  top : 0;
}

bootstrap だと▼の sticky-top です。
https://getbootstrap.com/docs/5.2/helpers/position/#sticky-top

scrollSpyってなんだ?

パソコン向けのページで、サイドバーに目次を表示してて、スクロールしていくとスクロールに合わせて、目次が変わっていくのを見かけたことがありませんか?

現在どこを読んでいるか分かる有りがたい機能です。

bootstrap だと次のページです。
ここのデモを見ると「あ、あれか!」ってなりますね。
https://getbootstrap.com/docs/5.2/components/scrollspy/

sticky と scrollspy を同時に使うとなにが問題なのか?

sticky って見出しを画面上に固定するものです。
つまり、その見出しの上下方向の位置が変わってしまってます。

で、目次からメニューをクリックすると変なところに飛んじゃいます。

具体的な再現手順としては次のようになります。

  1. 適当に下の方までスクロールして移動していく
  2. 現在の位置より上にある見出しの目次をクリックする

sticky と scrollspy を同時に使うために

今回、jQueryが使えたので jQuery を使ってますが、そんなに難しいことをしてないので、バニラjsとかTypeScript とかの方も変換は簡単ですよね。

jQuery(function($) {
    'use strict';

    // sticky と scrollspy の対策
    (function(){

        $('#目次を囲むid').find('a').click(function(){

            const $target = $(this.hash);
            let scroll_top = -1;

            $target.each(function(){
                const style = window.getComputedStyle(this);

                scroll_top = $target.offset().top;
                if (style) {
                    if (style.position === 'sticky') {
                        this.style.position = 'static';
                        scroll_top = $target.offset().top;
                        this.style.position = 'sticky';
                    }
                }
                return false;
            });

            if (scroll_top !== -1) {
                scroll_top -= 150;
                $('html, body').animate({scrollTop: scroll_top}, 200, 'swing');
            }

            return false;
        });
    })();
});

キモとなる流れは次のとおりです。

  1. 目次の <a> のクリックイベントを置き換える
  2. <a> のターゲット(見出し)の style.position が sticky になってるか判定
  3. sticky 以外ならそのままでOK
    sticky なら static に変更し、その位置を取得、で、sticky に戻す
  4. スクロール先にアニメーションしながらスクロール移動
  5. 上にイベントを伝搬させない

開発・技術入サポート

ということで宣伝です。

弊社では有償でBootstrap案件も行っていますので、お気軽にお問い合わせください。
Bootstrapは2011年(初期バージョン)から触り続けてきていることもあり得意中の得意です。

特にプログラム開発が必要になるようなカスタマイズは遠慮なくご相談ください。

メールやSNSなどのメッセージで簡単に連絡いただいたあとで、電話していただけると確実です。

※電話にはスカイプ・Google Meet・Zoomなども含みます。

デザイナーさんや営業・ディレクションをされてる方は特に歓迎です。