Bloggerのカスタマイズ VIII 目次スクリプトの変更

published_with_changes 更新日:

labelBloggerカスタマイズ

ほぼ1年ぶりに Blogger QooQ を弄ります。今まで使っていた目次の自動作成スクリプトが調子が悪いので、別のスクリプトに変更します。 備忘録ブログを残しているので、HTMLのどこを直せば良いのかが分かって助かります。

今までのものはとても 有名なスクリプトなのですが、私の環境では妙な目次になっていました。原因は、直接書きの「作成ビュー」と「HTMLビュー」を交互に切り換えながら記事を書く私の書き方だと思います。mathjaxの数式かもしれません。いづれにしろ、ブログ記事のHTMLのフォーマットが乱れているのだと思います。どうすることもできなくて、手をつけず(気にかけず)にしていたのですが、思い立ってあれこれ try and error をやってみることにしました。

目次
  1. 不具合の状況
  2. 変更した目次スクリプト
    1. カスタマイズしたCSS
      1. デザイン
      2. 行頭アイコン
      3. 反転ホバーアニメーション
  3. 開閉式の目次に改造(追記)
    1. detailsとsummaryタグの使い方
    2. HTMLの改造
    3. 調整したCSS
  4. サイドバーにも目次を追加
    1. サイドバー目次のスクリプト追加
    2. サイドバー目次のスクロール固定

不具合の状況

下図は左が今までの目次で、右が今回変更した目次です。この記事のひとつ前の記事の目次です。

h2タグの目次は正しいのですが、本来、Aの部分に表示されるべき3つの事例のh3タグ目次が、Aでは欠落しており、あるはずのないBやCの位置に出ています。また、別のh3タグ目次の”1.4 LTspiceのシミュレーション”は ”2.対数スイープ”の下にあるべきですが、別の場所に表示されています。

表示位置と番号付けが狂っています。さらに、これらをクリックしても、そこにはジャンプしません。目次からたどると、自分の書いた記事なのに混乱してしまいます。

左:おかしくなっている目次  右:正常に並んでいる目次


変更した目次スクリプト

正常な目次になるスクリプトを try and error で探し、次の引用元に紹介されているスクリプトに変更しました。このスクリプトの特徴は
  • 全然違うコード
  • シンプル
  • カスタマイズ性
とのことです。正常に目次表示ができることを確認した後に、CSS部分をいじってデザインを好みにカスタマイズをしてみました。

[Blogger] 目次を自動生成する方法(カスタマイズ方法とスクロールアニメーション付き)

[Blogger] 目次を自動生成する方法(カスタマイズ方法とスクロールアニメーション付き)

この記事では、Bloggerで目次を自動で追加する方法をご紹介します。コピペでOKです。目次のカスタマイズ方法と、各見出しを押した時のスクロールアニメーション(瞬間移動ではなく、スルスルっと移動するやつ)の追加方法も合わせてお伝えします。


スクリプトを書き込む位置は、引用ブログに説明がありますが、</head> の直前です。今まで使っていた目次スクリプトの位置と同じなので、上書きしました。jQuery は以前導入していました。

カスタマイズしたCSS

デザイン

<style>
/* 目次全体デザイン */
#toc{
background:#F9F9F9;
border:none;
display:block;
border-top:5px solid;
border-top-color:#00bcd4;
box-shadow: 0 2px 2px rgba(0,0,0,0.2);
padding: 0px 25px;
font-size:90%;
width:auto; /*幅を文字長さに合わせる*/
display:table;  /*幅を文字長さに合わせて中央寄せ*/
margin-left:auto;margin-right:auto;
}
/* 目次の文字指定 */
#toc-header {
text-align:left;
margin: 0 20px 20px -10px;
padding-left: -20px;
font-size:1.25em;
font-weight: 700;
color:#00acc1;
border-bottom:1px solid black;  /*下線*/
}
/* 目次のアイコン設定 */
#toc-header ::before {
top: 0;
left: -45px;
width: 50px;
height: 50px;
font-family: &quot;Font Awesome 5 Free&quot;;
content : &quot;f03a&quot;;
font-size:1em;
margin-right:10px;
color:#FFF;
background-color:#00acc1;
border-radius: 20%;
padding:14px;
}
/* 目次のデザインカスタマイズ */
#toc a{ /*リンク部分*/
color:#779cff;  /*文字色*/
font-size:100%;
margin-left:5px;
}
.h2list,.h3list,.h4list{
border:none;
margin:0;
}
.h2list{
list-style-type: "f138";
font-family: "Font Awesome 5 Free";
color:#5877b5;
font-weight: bold;
}
.h3list{
margine: 100px;
list-style-type:&quot;1405&quot;;  /* Canadian Syllabics */
}
.h4list{
list-style-type:disc; /* 塗りつぶされた円 */
}
#toc a:hover{
color:#ffffff;
background:#00bcd4;
border-radius: 2px;
}
</style>
CSS

見かけをちょっとだけ豪華にするため、リストの40行目まではまるっと変更しています。色使いをブログ画面と同じにして、さらに背景を浮き上がらせ、目次タイトルには Font Awesome のアイコンを追加しました。

カスタマイズCSSを適用した新しい目次


14行の margin ..... は目次をセンター配置させるための魔法のです。13行だけにして、これを書かないと左揃えとなります。全幅表示にするには、13、14行を削除すると左揃えの全幅表示になりました。これもいい感じでした。

目次デザインの元になったのは、うまく表示できるスクリプトを探しているとき目にした次のブログです。ブログのソースを見て 引用( パクリ  <m(__)m>  )させていただきました。

Bloggerブログ|記事中のh2を利用して目次を自動生成する(ページ内リンク)|jQuery

Bloggerブログ|記事中のh2を利用して目次を自動生成する(ページ内リンク)|jQuery

もくじを自動生成する方法について取り上げています。h2タグでマークアップされた文を抽出しもくじとして表示させています。jQuery使用。


行頭アイコン

目次の前に番号づけをするのが、52、59、62行の  list-style-type:..... の構文です。

リストスタイルは、こちらのサイトで一覧が見れます。使うかどうかは別として、かなりいろいろ選べます。 list-style-type - CSS: カスケーディングスタイルシート | MDN 引用元: [Blogger] 目次を自動生成する方法(カスタマイズ方法とスクロールアニメーション付き)

スクリプトの引用元にある説明をクリックすると、” カスケーティングスタイルシート” の詳細説明に飛びます。適用できる文字はテキストとか汎用の記号だけかと思っていたのですが、この冒頭に

list-style-type: "1F44D"; // thumbs up sign

 

という事例が載っていました。調べると、 "1F44D" は Unicode キャラクター図鑑 の”いいね” マークです。

そこで、気に入ったアイコンの unicode を調べて、ここに書くとアイコン付きのリストになりました。さらに、ここには  Font Awesomeのアイコンを使うこともできるようです。51行からの h2list にはFont Awesome のアイコンを使ってみました。

これに気づく前には、 【CSS】リストのスタイルをFontAwesomeアイコンに変更する方法に倣って次のように書いてみたのですが、全行にアイコンがついてしまいうまくいきませんでした。

list-style-type: none;
}
.h2list ::before {
font-family: "Font Awesome 5 Free";
content: "f105";
position: absolute;
left : 10.5em;
color:#5877b5;
font-weight: bold;
}
CSS


今回、変更していませんが、目次の行頭は番号からアイコンにしたので、オリジナルのスクリプトの ”ol”タグは”ul”タグに変えた方が良かったのかもしれません。あるいは、目次自体は順番を意識したものなので、”ol”タグ がやはり正しい使い方かもしれません。


<<  追記  >>

後日、"ul"タグへ変更しました。行頭の符号を番号式にしていないので、変化はありません。

さらに、使用しているアイコンフォントを Unicode キャラクター図鑑 のものへ変更しました。"Font Awesome" と "Google Material Icons" を使っていたので、統一したかったのが変更の理由です。どちらへの統一でも良かったのですが、どちらも問題がでました。

  • "Font Awesome" では、目次以外で表示されないアイコンが結構あった。(理由不明)
  • "Google Material Icons" では、目次の表示が崩れた。

反転ホバーアニメーション

マウスを置くと表示が反転するホバーアニメーションをつけました。これは、64行からの構文です。

開閉式の目次に改造(追記)

過去のブログを遡って目次に注目して眺めていたら、目次数の多い記事はその表示が気になりだしました。元の目次では表示/非表示動作ができたのですが、変更した目次にはその機能がありません。ならばとよくばり根性で、見よう見まねの改造をしてみます。

googleのキーワード検索してみると、blogger では ”details タグと summary タグを使って折りたたみ式にする” 方法がたくさんヒットしましたので、これを適用してみます。

ヒントをいただいたのはこのブログです。

Blogger 目次を自動生成するスクリプト | リモスキ

Blogger 目次を自動生成するスクリプト | リモスキ

Blogger に目次を自動表示するスクリプトを作成したので、使い方とあわせて紹介します。


そして、details/summaryタグ の使い方をイメージできたのでは、このブログのおかげです。

detailsとsummaryタグでアコーディオンを作る - HTMLリファレンス

detailsとsummaryタグでアコーディオンを作る - HTMLリファレンス

HTMLのdetailsタグとsummaryタグを合わせて使えば、簡単にアコーディオンを作ることができます。CSSの装飾サンプルやアニメーションのかけ方についても合わせて解説します。


detailsとsummaryタグの使い方

<summary>と</summary>で囲われた部分は常に表示されます。そして、ここをクリックすると、それまで折りたたまれていた<details>と</details>で囲われた部分が現れるというタグの機能です。

[[HTML]]

<details>
  <summary>常に表示されている・トグルスイッチの役目</summary>
  <p>ここは「表示」と「非表示」が交互に切り換わる</p>
</details>
このHTMLの動作確認に、試しに作ってみました。消し方がわからず、1行目にはsummaryアイコンの痕跡が残っています。
常に表示されている・トグルスイッチの役目
(ここをクリック)

ここは「表示」と「非表示」が交互に切り換わる


HTMLの改造

<details id="toc" >
   <summary class="toc-header">目次(タイトル)</summary>
   折りたたむ目次リスト
</details>
Markup

と書けば、目次の表示/非表示が実現できそうです。そこで、これを目次スクリプト引用元の   さんのHTMLに適用してみます。

改造箇所はHTML最後の</script>から3行手前の目次を構成している構文です。

[[オリジナル]]

$(".post-body h2").first().before("<div id='toc'><div id='toc-header'><p>目次</p></div>"+toc+"</div>");    


[[改造]]
$(".post-body h2").first().before("<details id='toc'><summary class='toc-header'>目次</summary>"+toc+"</details>");    

 デフォルトでは目次を折りたたんだ場合のHTMLです。デフォルトで開く目次にする場合には、<details id='toc' open> とします。

幸運にも、これでうまくいきました。
目次枠のデザインはそのままでは移行できないようです。CSSの調整が必要でした。

調整したCSS



<style>
/* 目次全体デザイン */
#toc{
background:#F9F9F9;
border:none;
border-top:5px solid;
border-top-color:#00bcd4;
box-shadow: 0 2px 2px rgba(0,0,0,0.2);
padding: 0px 25px;
font-size:100%;
max-width: 60%; /*幅を画面に合わせる width: auto が効かない*/
display:table;  /*幅を文字長さに合わせて中央寄せ*/
margin-left:auto;margin-right:auto;
}
/* 目次の文字指定 */
.toc-header {
text-align:left;
margin: 5px 20px 10px -10px;
padding-bottom: 5px;
font-size:1.25em;
font-weight: 700;
color:#00acc1;
border-bottom:1px solid black;  /*下線*/
}
/* summaryの矢印を消す */
summary {
position: relative;
display: block; /* 矢印を消す */
padding-left: 20px; /* アイコン分の余白 */
cursor: pointer;
}
summary::-webkit-details-marker {
display: none; /* 矢印を消す */
}
/* 疑似要素でアイコンを表示 */
/* 閉じたときの目次のアイコン設定 */
summary::before{
color: #00acc1;
font-family: "Font Awesome 5 Free";
content: '\f03a';
margin-right: 10px;
}
/* 開いたときの目次のアイコン設定 */
details[open] summary::before{
font-family: "Font Awesome 5 Free";
content: '\f03a';
color:#FFF;
background-color:#00acc1;
border-radius: 20%;
padding: 5px;
}
/* ふわっと出てくるアニメーション設定 */
details[open] .h2list {   /* クリックしたら表示される要素 */
overflow: auto;
animation: fadeIn 1s ease;  /* fadeIn秒の設定 */
}
@keyframes fadeIn {
	0% {
	opacity: 0;   /* 最初は見えない状態 */
	transform: translateY(-20px); /* 20px上にずらしておく */
	}
	100% {
	opacity: 1; /* fadeIn秒後に見えるように */
	transform: none;  /* 20pxずらしたものを取り除く */
	}
}
/* 目次の折りたたみ */
#toc .toc-header:after {
content: '[ひらく]';
margin-left:.5em;
}
#toc[open] .toc-header:after {
content: '[とじる]';
}
/* 目次のデザインカスタマイズ */
#toc a{ /*リンク部分*/
color:#779cff;  /*文字色*/
font-size:100%;
margin-left:5px;
}
.h2list,.h3list,.h4list{
border:none;
margin:0;
}
.h2list{
list-style-type: &quot;\f138&quot;;
font-family: &quot;Font Awesome 5 Free&quot;;
color:#5877b5;
font-weight: bold;
}
.h3list{
margine: 100px;
list-style-type:&quot;\1405&quot;;  /* Canadian Syllabics */
}
.h4list{
list-style-type:disc; /* 塗りつぶされた円 */
}
#toc a:hover{
color:#ffffff;
background:#00bcd4;
border-radius: 2px;
}
</style>
CSS


開閉式目次の参考にした記事に合わせて、折りたたみ要素(toc)をid属性、目次タイトル(toc-header)をclass属性にしています。スタイルの呼び出しには、id属性は#、class属性は.(dot)を使うとのことで、toc-headerはそれに変えています。

summaryタグで表示する”目次”の前後(before, after)の構文が新規追加になっています。".toc-header :before"タグを使うのではなく、"summary :before"タグを使うルールです。(これに気づかず、結構悩みました。)

また、折りたたみが”ふわっと出てくるアニメーション”を入れてみました。

構文ルールを知らないので、Google先生とdeveloper tool とをにらめっこしながら、他にも try and error で表示変更や位置の微調整をしています。パッチワークを多用して、やっと仕上がったのが上記のCSSです。


サイドバーにも目次を追加

目次を見ようと思うと、記事の途中でも最上部の目次に戻らなければならないことが気になっていました。今回、色々な方のブログを目次に着目して調べたので、サイドバーに目次を置いているブログがあることに気づきました。それに、スクロールしてもサイドバー目次が消えないで残るブログもあります。

この機能を組み入れます。

ただし、目次引用元の   さんのブログはサイドバー目次の機能は備わっているものの、その解説記事はまだ書かれていない模様でしたので、ソースから 引用( パクリ <m(__)m> )させていただきました。


サイドバー目次のスクリプト追加

HTMLを直接編集することもできますが、「レイアウト」から、 sidebarの新しい「ガジェットを追加」をクリックして、「HTML/JavaScript」を選んだ方が間違いがありません。


「HTML/JavaScript」を選び、新しいガジェット(ヴィジェット)を編集します。表示されるタイトルを ”目次” にして、コンテンツにサイドバースクリプトを貼り付けで保存します。これで出来上がりです。




サイドバー目次のスクリプトは、オリジナルからアイコン付きにモディファイ(太字)しています。ホバーアニメーションは サイドバー全体に適用しているので、それが効いています。

サイドバー目次のスクリプト
<!-- [START] TOC Sidebar -->
<script defer='defer'>
$(function() {
var toc="<ol class='h2list'>";
var h2cnt=0;
var h3cnt=0;
var h4cnt=0;
$(".post-body h2,.post-body h3,.post-body h4", this).each(function() {
var prefix="";
var caption=$(this).text();
var chapter="";
var node=this.nodeName.toLowerCase();
if (node == "h2") {
if(h3cnt>0 && h4cnt==0){
    prefix = "</li></ol></li>";
}else if(h4cnt>0){
    prefix = "</li></ol></li></ol></li>";
}else{
    prefix = "</li>";
}
h2cnt++;
h3cnt=0;
h4cnt=0;
chapter+=h2cnt;
} else if (node == "h3") {
if(h3cnt==0){
    prefix = "<ol class='h3list'>";
}else if(h4cnt>0){
    prefix = "</li></ol></li>";
}else{
    prefix = "</li>"
}
h3cnt++;
h4cnt=0;
chapter+=h2cnt+"-"+h3cnt;
} else if (node == "h4") {
if(h4cnt==0){
    prefix = "<ol class='h4list'>";
}else{
    prefix = "</li>";
}
h4cnt++;
chapter+=h2cnt+"-"+h3cnt+"-"+h4cnt;
}
toc += prefix + "<li><a href='#" + chapter + "'><span>" + caption + "</span></a>";
});
toc+="</li></ol>";
$('#toc-side').get(0).insertAdjacentHTML('beforeend',toc);
});
document.currentScript.parentNode.insertAdjacentHTML('beforeend','<div id="toc-side"></div>');
</script>

<style>
#toc-side ol{
border:none;
background:none;
margin:0;
padding-left:1.5em;
}
#toc-side .h2list li{
margin:0;
list-style-type:"1F44D"; /* thumbs up sign */
}
#toc-side .h3list li{
padding-left: 5px;
list-style-type:"1405";  /* Canadian Syllabics */
}
#toc-side .h4list li{
list-style-type:disc;
}</style>
<!-- [END] TOC Sidebar -->
Markup


メインの目次は h2タグが無ければ目次を生成しないのですが、こちらはh2タグの見出しがなくても、h3タグの見出しで目次が生成されるようです。(具体例はこのブログ

サイドバー目次のスクロール固定

”スクロールしてもサイドバー目次が消えない機能”は、このタイトルの表現が正しいと思うのですが、なぜか "スクロール追従" という表現が普通に使われています。

私のブログは QooQ で作っているので、”QooQ  スクロール追従” のキーワードで検索すると次のブログが最初に出てきます。スクロール固定の方法は、4行のCSSを書くだけのようです。

【QooQ】サイドバーウィジェットを追従させる方法 | ふじろじっく

【QooQ】サイドバーウィジェットを追従させる方法 | ふじろじっく

QooQ で何故かついてこないサイドバーウィジェットを追従させる方法


#sub-content .widget:last-child {
    position: sticky;
    top: 0;
}
Markup


CSSを置く場所でトラブルのも嫌だったので、HTMLの編集ではなく、設定画面の「テーマ」→「カスタマイズ」から、「詳細設定」を選び、下図のようにたどって、「CSSを追加」しました。



この引用元のブログ主さんも、始めはスクロール追従しなかったのだけれど、試行錯誤して上記のCSSでうまくいったようです。うまくいかないときは、下記のことをやるようにも説明されています。

  • 一番下に JavaScript 等の見えないウィジェットを置いてる場合は上に移動させるか、
  • #sub-content .widget:last-child の部分を 追従させたいウィジェットの ID に変えてください。
  • ナビバーを固定させてる場合は、top の値をナビバーの高さに合わせて調整してください。
引用元: 【QooQ】サイドバーウィジェットを追従させる方法

みんなやってみましたが、私のケースでは全く効くようになりませんでした。

CSSに出てくる  position: sticky; とは、” スクロールした際に指定した要素を指定した位置に貼り付けるプロパティ” とのことで、これが効かない事例/原因がWebに色々説明されています。が、小生は見様見まねでブログを作っているので、なんとなくの雰囲気しか分かりません。

まず考えられる原因(これが一番多いらしい)は、 overflow-hiddeの属性が親要素に設定されていることらしいですが、当ブログの場合はナビバーへの適用だけでした。

次の原因として、何となくイメージできたのは、

  • 2カラムでメインとサイドバーがあるような場合、サイドバーにposition: sticky;を適用しないと効かない。
  • メインカラムとサイドカラムの2カラム構成になっている場合、両カラムの高さが同じでないと効かない。縦方向の高さが少ないと効かない。
といったことが原因のもようで、対策は” display: flex;を使って要素を横並びにすると、自動で高さも揃います。 ” らしいです。

この予備知識を元に、改めてサイドバー目次の引用元のソースを覗くと、次のようになっていました。これを適用すると、うまく止まるようになりました。top: 50px; も適値でした。


/* sticky sidebar contents */
#sub-content {
display:flex;
}
#sub-content .widget:last-child {
position: sticky;
top: 50px;
}
CSS


Powered by Blogger | Designed by QooQ

keyboard_double_arrow_down

keyboard_double_arrow_down