Bloggerに関するカスタマイズ・テンプレート・TIPSを紹介しています。

2026/02/25

Bloggerのサイドバーに追従式の目次を設置する

event_note2月 25, 2026 editBy まつゆう forumNo comments

これはなに?

このコードは、Bloggerなどのブログのサイドバーに 目次(Table of Contents)を自動表示 するためのスクリプトです。

読者が記事を読みやすくなるだけでなく、ブログ全体の利便性も向上します。

この目次の機能・特徴を紹介

  • 自動生成:記事の見出しを自動で取得して目次を作成
  • 階層表示:<h3> は少しインデントされてサブ項目として表示
  • サイドバー固定(追従):
    • このスクリプトは「目次が設置されているガジェット」を認識して固定
    • 記事をスクロールしても画面上部に追従し、常に目次が見える
    • フッターに到達すると自動で停止して重ならないよう調整
  • ハイライト:現在の表示位置に応じて目次項目が強調表示
  • フッター衝突回避:サイドバーがフッターと重ならないように調整

コード


<div id="toc-custom-widget" class="toc-widget-container">
  <div class="toc-label">CONTENTS</div>
  <div id="toc-content-area" class="custom-toc-wrapper"></div>
</div>

<script type="text/javascript">
(function($){
    $(window).on('load', function(){
        var $postBody = $('.post-body, .entry-content, .item-post-inner').first();
        var $tocArea = $('#toc-content-area');
        var $widget = $('#toc-custom-widget');
        var $parentGadget = $widget.closest('.widget');
        
        if ($postBody.length === 0 || $tocArea.length === 0) return;

        var $headings = $postBody.find('h2, h3');
        if ($headings.length > 0) {
            var $ul = $('<ul></ul>');
            $headings.each(function(i, el){
                var id = 'toc-point-' + i;
                $(el).attr('id', id);
                var li = $('<li></li>');
                if(el.tagName === 'H3') li.css('padding-left','15px');
                var a = $('<a href="#'+id+'" class="toc-link">'+$(el).text()+'</a>');
                a.on('click', function(e){
                    e.preventDefault();
                    $('html, body').animate({scrollTop: $(el).offset().top - 90},500);
                });
                li.append(a);
                $ul.append(li);
            });
            $tocArea.empty().append($ul);
            $widget.css('visibility','visible'); // 描画完了後に表示
        } else {
            $parentGadget.hide();
            return;
        }

        var offset = $parentGadget.offset().top;
        var originalWidth = $parentGadget.width();
        var $footer = $('#footer, footer, .footer-wrapper, #footer-wrapper').first();

        function updateTocPosition(){
            var scrollTop = $(window).scrollTop();
            var windowWidth = $(window).width();
            if(windowWidth > 768){
                var footerTop = $footer.length ? $footer.offset().top : $(document).height();
                var widgetHeight = $parentGadget.outerHeight();
                var topPadding = 20;
                var stopLimit = footerTop - widgetHeight - topPadding - 30;

                if(scrollTop > offset){
                    if(scrollTop > stopLimit){
                        $parentGadget.css({
                            'position':'absolute',
                            'top': stopLimit+'px',
                            'width': originalWidth+'px',
                            'z-index':'99'
                        });
                    }else{
                        $parentGadget.css({
                            'position':'fixed',
                            'top': topPadding+'px',
                            'width': originalWidth+'px',
                            'z-index':'99'
                        });
                    }
                }else{
                    $parentGadget.css({'position':'static','width':'auto'});
                }
            }else{
                $parentGadget.css({'position':'static','width':'auto'});
            }

            // ハイライト
            var activeId = "";
            $headings.each(function(){
                if($(this).offset().top < scrollTop + 120){
                    activeId = $(this).attr('id');
                }
            });
            $('.toc-link').removeClass('active');
            $('.toc-link[href="#'+activeId+'"]').addClass('active');
        }

        $(window).on('scroll resize', updateTocPosition);
        updateTocPosition(); // 初回
    });
})(jQuery);
</script>
  

設置方法

  • HTMLガジェットの追加
    Bloggerの「レイアウト」→「ガジェットを追加」→「HTML/JavaScript」→ 上記の <div id="toc-custom-widget">…</div><script> を貼り付け
  • CSSはテーマに合わせて調整
  • 色や幅、背景などを好みに変更可能
  • 初期状態では目次が非表示になっている場合は visibility を確認
  • 記事本文に <h2><h3> を設定
    目次はこれらのタグから自動生成される

コードの中から重要な点を解説

動的なID付与とリンク生成
$headings.each(function(i, el){ ... }) の部分で、記事内の見出しに toc-point-0 から順にIDを自動で割り振っています。これにより、手動でアンカーを埋め込む手間を省き、目次クリック時の正確なジャンプを実現しています。
スマートな表示制限ロジック
if ($headings.length > 0) で見出しの有無を判定し、見出しがない場合は $parentGadget.hide() によってガジェット枠ごと非表示にしています。これにより、サイドバーに「空のタイトル」だけが残る不格好な状態を防いでいます。
精密な追従・衝突回避計算
updateTocPosition 関数内の stopLimit 計算が重要です。フッターの位置(footerTop)と自身の高さ(widgetHeight)を計算し、フッターに到達した瞬間に fixed(固定)から absolute(絶対配置)へ切り替えることで、フッターを突き抜けて重なる問題を回避しています。
読者の現在地を示すハイライト機能
スクロールに合わせて activeId を更新し、目次の該当リンクに active クラスを付与しています。これにより、ユーザーは「今、記事のどのあたりを読んでいるのか」を視覚的に把握できます。

注意点

  • モバイル表示:幅768px以下では固定解除され、通常の位置に表示
  • jQuery必須:このスクリプトはjQuery依存
  • サイドバー幅:ウィジェット幅が自動計算されますが、テーマによっては調整が必要
  • 読み込みタイミング:記事本文のレンダリング後に目次が生成されるため、初回表示が少し遅れる場合あり
  • 複数目次:1ページに複数の同様の目次ガジェットは推奨されません
まつさん
まつさん
目次が表示されてからサイドバーが固定される仕様にはなっているはずです。その仕様でサイドバーが効かないケースもあることをご了承ください。許してニャン🐱
まつゆう
アラフォーゲーマーがいろんなゲームを楽しみながらプレイしています。YouTube・Twitch・Mixerで配信中!! 東京パフォーマンスドールの狂信者。 好きすぎてドメインを取得してファンサイトを運営中。

0 comments:

コメントを投稿