
目次を自動生成してくれるスクリプトを導入しました。
実は今まで当ブログの一部の記事・ページに付けていた目次は完全に手入力の人力作成💧だったんですが、今後は何もしなくても見出しの含まれる記事では勝手に表示してくれるようになるので、記事作成も楽になります。
こちらのスケ郎さんが作られたスクリプトを手順通りに設置しただけで簡単に導入できました。
スケ郎のお話
[Blogger] 目次を簡単に自動生成(忙しい人向けのコピペ素材)https://www.sukerou.com/2018/10/blogger-table-of-contents-javascript.html
デザインはこれまでの人力目次と同じになるように調整しています。その他細かい所も自分好みにカスタマイズ済み。
↓が自動生成された目次です。
IB-Note 作の自動生成目次に乗り換えました。
CONTENTS
表示・非表示ボタンいる?
ところで前から疑問に思っていたのですが、この手の目次には必ず「表示・非表示(隠す)」ボタンというものが付いていますけど、これっていりますかね?

デフォルトで非表示状態にしているのであれば、当然「表示(開く)」ボタンは必要になりますけど、初めから開いてる場合、わざわざ閉じる人なんています? 中には目障りに感じる人とかいるんだろうか・・・(~_~;)
私はそんな人はいないであろうという判断で、開閉ボタンは消しました。無くても何ら支障はないはずだと思いますけどどうでしょう。
ふじろじっくカスタム
ちなみにうちでカスタマイズした内容は…
- 開閉ボタンは display:none で消しました。
- 「これ以降のソースは編集しないでください」という部分もちょっとだけいじってます(^^;
- 記事だけでなく固定ページにも表示させたいので、条件分岐タグを以下のように変更しました。
<b:if cond='data:blog.pageType == "item"'>
↓
<b:if cond='data:view.isSingleItem'>
<!-- [START] 目次作成プラグイン--> <b:if cond='data:view.isSingleItem'> <script> //<![CDATA[ //以下のオプションを好みに合わせて変更して下さい //オプションの詳しい説明は、(https://www.sukerou.com/2018/10/blogger-table-of-contents-javascript.html)を参照 var toc_options = { target: ["h2", "h3", "h4"], autoNumber: true, condTargetCount: 3, insertPosition: "firstHeadBefore", showToc: true, width: "100%", marginTop: "2em", marginBottom: "3em", indent: "0", postBodySelector: ".widget.Blog" }; //これ以降のソースは編集しないでください (function(i){var j=0;document.addEventListener("DOMContentLoaded",function(){var p=document.querySelector(toc_options.postBodySelector);if(p==null||typeof p==="undefined"){reutrn}if(toc_options.target.length==0){return}rootContent=h(toc_options,p);if(rootContent.children.length>=toc_options.condTargetCount){var q=c(rootContent);o(q)}});function h(q,p){var u=q.target.length;var t=function(E,D,w){var z=q.target[E];var x=E<u-1?q.target[E+1]:"";var y="toc_"+(++j);var F=g(z,m(D),E+1,y);w.children.push(F);D.id=y;var A=f(D);if(x==""){return}while(true){if(A==null||typeof A==="undefined"){break}if(b(A)==z){break}if(b(A)==x){t(E+1,A,F)}else{var B=A.getElementsByTagName(x);for(var C=0;C<B.length;C++){t(E+1,B[C],F)}}var A=f(A)}};var r=g("ROOT","",0);var v=p.getElementsByTagName(q.target[0]);for(var s=0;s<v.length;s++){t(0,v[s],r,"")}return r}function c(s){var r=document.createElement("div");r.classList.add("b-toc-container");r.style.marginTop=toc_options.marginTop;r.style.marginBottom=toc_options.marginBottom;if(toc_options.width=="100%"){r.style.display="block"}else{r.style.width=toc_options.width}var q=document.createElement("p");var w=document.createElement("span");var v=document.createElement("span");var u=document.createElement("span");v.classList.add("b-toc-show-wrap");u.classList.add("b-toc-show-wrap");var y=document.createElement("a");w.innerText="目次";v.innerText=" [";u.innerText="]";y.href="javascript:void(0);";q.appendChild(w);q.appendChild(v);q.appendChild(y);q.appendChild(u);var t=function(z){var p=typeof z==="boolean"?z:e(r,"hide");if(p){y.innerText="非表示";r.classList.remove("hide")}else{y.innerText="表示";r.classList.add("hide")}};y.addEventListener("click",t);t(toc_options.showToc);var x=document.createElement("ul");s.children.forEach(function(z,p){n(x,z,(p+1)+"")});r.appendChild(q);r.appendChild(x);return r}function n(s,u,w){var p=document.createElement("li");var q=document.createElement("a");p.style.paddingLeft=toc_options.indent;q.href="#"+u.id;if(toc_options.autoNumber){var t=document.createElement("span");t.classList.add("toc-number");t.innerText=w}var v=document.createElement("span");v.classList.add("toc-text");v.innerText=u.text;if(toc_options.autoNumber){q.appendChild(t)}q.appendChild(v);p.appendChild(q);s.appendChild(p);if(u.children.length>0){var r=document.createElement("ul");p.appendChild(r);u.children.forEach(function(y,x){n(r,y,w+"-"+(x+1))})}}function o(q){var r=null;var p=document.querySelector(toc_options.postBodySelector);if(toc_options.insertPosition=="firstHeadBefore"||toc_options.insertPosition=="firstHeadAfter"){r=p.querySelector(toc_options.target[0])}else{if(toc_options.insertPosition=="top"){r=p}}if(r==null){return}if(toc_options.insertPosition=="firstHeadBefore"){k(r,q)}else{if(toc_options.insertPosition=="firstHeadAfter"){a(r,q)}else{if(toc_options.insertPosition=="top"){k(r,q)}}}}function g(q,r,p,s){return{tagName:q,text:r,children:[],nestLevel:p,id:s}}function m(p){return p.innerText}function f(p){return p.nextElementSibling}function d(p){return p.previousElementSibling}function b(p){return p.tagName.toLowerCase()}function e(p,q){return p.classList.contains(q)}function l(p){return p.parentNode}function a(q,s){var r=l(q);var p=f(q);if(r!=null&&p!=null){r.insertBefore(s,p)}}function k(p,r){var q=l(p);if(q!=null){q.insertBefore(r,p)}}})(window); //]]> </script> <style type="text/css"> .b-toc-container { position: relative; background:#fff; border:1px solid #eee; border-radius:8px; display: table; padding:1.5em; margin-right: auto; margin-left: auto; box-shadow:10px 10px 15px -10px #aaa; width:80%; } .b-toc-container p { text-align:center; margin:0; padding:0; } .b-toc-container p span:nth-of-type(1) { font-weight:bold; font-size:1.3em; font-family:arial; color:#555; } .b-toc-container ul { list-style-type:none; list-style:none; margin:0; padding:0; } .b-toc-container > ul { margin:15px 0 0; } .b-toc-container.hide > ul { display:none; } .b-toc-container ul li { margin:0; padding:0 0 0 10px; list-style:none; line-height:1.7em; } .toc-number { font-weight:bold; padding-left: 5px; } .toc-number:after { content:"\002E"; } .b-toc-container ul li a { color:#42a5f5; display: flex; /*折返し調整の追記*/ align-items: flex-start; /*折返し調整の追記*/ flex-wrap: nowrap; /*折返し調整の追記*/ } .b-toc-container ul li .toc-number { margin:0 5px 0 0; white-space: nowrap; /*折返し調整の追記*/ } .b-toc-container ul li a:hover { color: #fff!important; text-decoration: none!important; background: #6495ed; } /*表示・非表示ボタン*/ .b-toc-container p a { display:;/*ボタンを非表示にする場合は none*/ position: absolute; right: 10px; top: 10px; font-size: .7em; color: #111!important; line-height: 1.8em; text-decoration: none!important; padding: 0 5px; background: #ddd; border-radius: 2px; opacity: .8; } .b-toc-show-wrap { display: none; } .b-toc-container p a:hover { opacity: 1; color: #333!important; } </style> </b:if> <!-- [END] 目次作成プラグイン-->
ヌルっと移動
さて、目次は満足いく形で設置できましたけど、さらにもっと見栄え良くなるようなカスタマイズを施したいなというわけで、スムーススクロールというものも実装してみました。
瞬間移動よりこっちの方がいいでしょ?
スムーススクロールのスクリプトはこちらの記事を参照させていただきました。
TechAcademyマガジン - 教育×テクノロジーのWebメディア
jQueryでスムーススクロールを実装する方法 | TechAcademyマガジンプログラミング初心者向けに、jQueryでスムーススクロールを実装する方法について解説しています。Webサイトでもよく見る「トップに戻る」ような機能を手軽に作ることができるので、ぜひ自分で書いてみましょう。https://techacademy.jp/magazine/9532
当ブログでは元々 jQuery は導入済みだったので、以下のスクリプトを追加するだけで実装できました。(jQuery より下に置かないと動作しない)
12行目のreturn false; は目次をクリックした時に URL 末尾に #アンカータグを付かなくするためのコードです。
うちでは true に変えています。つまりアンカータグが付くようになってます。
トップページでは必要ないのと、番号ページネーションのスクリプトと干渉するのを防ぐために記事・固定ページでのみ有効にする条件分岐タグも付けています。
<!--Smooth Scroll--> <b:if cond='data:view.isSingleItem'> <script> //<![CDATA[ $(function(){ $('a[href^="#"]').click(function(){ var speed = 1000; var href= $(this).attr("href"); var target = $(href == "#" || href == "" ? 'html' : href); var position = target.offset().top; $("html, body").animate({scrollTop:position}, speed, "swing"); return true; }); }); //]]> </script> </b:if>
目次を完全に表示させたくない場合
一般的にはそういうケースはあまりないのかもしれませんが、ウチでは見出しが複数あっても目次を表示させたくない記事やページがあります。(目次用途で見出しを付けてない等の理由)
目次を表示する見出しの数を、例えば「3」に指定すれば見出しが3つ未満の場合目次が表示されませんけど、指定した見出し数に関わらず目次を表示させたくない場合は、記事編集のHTMLモードで以下のスタイルコードを追記することで出したくない記事で非表示にしています。
<style>.b-toc-container{display:none!important}</style>
ちなみにスケ郎さん、目次を出す/出さないを選べる機能の実装も検討されているようです。→ 作者さんのコメント
初めからこういう選択機能があれば便利だと思うので、是非実装して欲しいです。
2020/01/14 追記: ナビバーと見出しが被る問題の改善方法
当ブログのようにナビゲーションバー(ヘッダーメニュー)が position:fixed 等で固定されている場合、スクロール停止位置の見出しにメニューが被ってしまうという問題がありますが、この問題を解決できる方法がありました。
上記スクリプトを以下のようにすると、ちょうどいい位置で止まってくれるようになります。
<!--Smooth Scroll--> <b:if cond='data:view.isSingleItem'> <script> //<![CDATA[ $(function(){ var headerHight = 30; //固定ヘッダーメニューの高さ(px) $('a[href^="#"]').click(function(){ var speed = 1000; var href= $(this).attr("href"); var target = $(href == "#" || href == "" ? 'html' : href); var position = target.offset().top-headerHight; $("html, body").animate({scrollTop:position}, speed, "swing"); return true; }); }); //]]> </script> </b:if>
【参考記事】
Tips Note by TAM
position:fixedでヘッダ固定時のページ内リンクのずれを解消したい | Tips Note by TAMTAM のテクニカルチームがお届けする WEB技術ブログ!http://www.tam-tam.co.jp/tipsnote/html_css/post4776.html
2020/05/19 追記: アップデート
昨日、目次の表示に関する修正がされましたので、当記事のコードもアップデートしておきました。(CSS の/*折返し調整の追記*/の4行)
[Blogger] 目次を簡単に自動生成(忙しい人向けのコピペ素材)(2020/05/18 追記)
長い見出しで文字列が折り返される場合に、目次番号の幅の分だけ字下げするように改善されました。

だいぶ見やすくなりましたね。
2022/04/24 追記
こちらの IB-Note さん作の自動生成目次スクリプトに変更しました。
スケ郎さんのものよりコードがシンプルで読み込みも早くておすすめです!
IB-Note
【全見出しタグ対応】高速&シンプルな自動生成目次 | IB-Noteいろいろな自動生成目次のソースコードを読んで比較検討を重ねた結果、「これだ!」と思う理想の目次を作ることができました。https://itblogger-note.blogspot.com/2021/12/fast-and-simple-auto-toc.html
コメントを投稿
別ページに移動します5 件のコメント (新着順)
BINUBALLさん、こんばんは。日本語でのコメントありがとうございます。
scroll-behavior: smooth は私も最近知りました。
このブログを IE で見に来る方はほとんどいないと思うので、私は IE 対応は考えないことにしているのですが、Safari も非対応らしいので導入するかどうかは迷います(^^;
BINUBALL 씨, 안녕하세요.일본어로의 코멘트 감사합니다.
scroll-behavior: smooth는 나도 최근 알았습니다.
이 블로그를 IE에서 보러 오는 쪽은 거의 없다고 생각하므로, 나는 IE 대응은 생각하지 않기로 하고 있습니다만, Safari도 비대응인 듯하므로 도입할지는 헤맵니다(^^;
簡単スムーズスクロールを適用する方法も存在します。
scroll-behavior:smooth
に、ちょうどieでサポートされていないんですね
(T_T)
ありがとうございます。
出来ました。
ありがとうございました。
あいうえおさん、コメントありがとうございます。
目次のホバー時の背景ハイライトに関しては、以下の CSS を目次コードの </style> の直前に追記すれば適用できます。
カラーコードはお好みで適宜変更してください。
.b-toc-container ul li a:hover{color:#fff!important;background:#6495ed;}
以上、ご参考まで。
参考にさせていただきました。
一つ質問なのですが、ふじやんさんの目次では、ホバー時に下線が出ず、背景全体がハイライトされていますが、どのようにカスタマイズされたのでしょうか?
教えていただけると幸いです。