今回は、Cocoonの目次のカスタマイズを紹介したい。
Cocoonの目次ブロックに設定されているCSSコードを確認しつつ、なるべく綺麗なカスタマイズを心掛けた。
Cocoonの目次機能とは
いろいろなWebサイトを見ていると、大抵は目次が表示されている。また、目次の見出しリストの見出しを押すと、読みたい記事まで飛ぶことが出来るはずだ。
そして、Cocoonには本文中に自動で目次が表示される機能が最初から付いている。
これにより、目次系のプラグインを入れる必要はない。
目次を有効化するには
管理者画面の左側のサイドバーに存在する、「Cocoon 設定」をクリックして、Cocoonのテーマの設定を変更する画面に入ろう。
そこで「目次」タブを開き、「目次を表示する」の項目にチェックが入っていたら、本文中に目次が表示されるようになっている。
もし、チェックが入っていなかったら入れておこう。
カスタマイズを行う前に設定する項目
子テーマのstyle.cssを編集する前に、Cocoon側で目次の表示設定を済ませる必要がある。
デフォルトのままだと、CSSを使って外観を編集する際のカスタマイズに少し難があるからだ。
Cocoonの目次の設定を管理する場所を簡単に説明する。
まず、管理者画面の左側のサイドバーに「Cocoon 設定」が存在するので、それを押してCocoonの設定画面に入ろう。
そして、上の切り替えタブを見て行くと、「本文」と「SNSシェア」の間に「目次」と書かれているタブがあるはずだ。
それを押すと、Cocoonの目次を設定する画面を開くことができる。

この画面が表示されているだろうか?
なお、上の画像の設定項目はすべてデフォルトの状態である。
目次ナンバーの項目の表示の変更
目次ナンバーの表示を「数字(デフォルト)」から「表示しない」に変更する。

左側に見出しの順番を自動的に表示する数字が存在していると、数字の桁や文字自体の大きさによりデザインが崩れ、対応が難しくなる。
また、Font Awesomeで目次内の見出しに自分でアイコンを付け加える場合は邪魔になってしまうのもある。
見出し内タグの項目にチェックを入れる
Cocoonのデフォルトの設定のままでは、記事に目次が表示されると見出し内に埋め込んだリンク(URL)が”ただの文字”になってしまう。
なので、目次が表示されても見出しに埋め込んだリンクが有効化されるように設定を変更する必要がある。
このように、「H見出し内のタグを有効にする」にチェックを入れよう。

画像のようにチェックを入れただろうか?
こうすることで、目次が表示されても見出しに埋め込んだリンクがリンクとして機能するようになる。
見出し内タグの項目の意味
なぜこの設定の変更を行う必要があるのか、もう少し詳しく説明したい。
今から下に表示するふたつの違いを見てほしい。
デフォルトではチェックが付いていないので、チェックを付けることを忘れないようにしよう。
目次の表示数の制限(推奨)
Cocoonのデフォルトの設定では、目次にH6タグまで表示されるようになっている。
しかし、それでは見出しの階層が深くなりすぎるので、見出しの表示数を制限する。

このように、目次に表示される見出しをH4タグまでに制限しよう。
こうすることで、目次もゴチャゴチャしなくなる。
これらを設定しなおし「変更をまとめて保存」ボタンを押そう。設定が変更されていることを確認したら完了となる。
これでカスタマイズをする前の設定の解説を終える。
子テーマのstyle.cssで目次をカスタマイズ
それでは、子テーマのstyle.cssにcssコードを入力して目次をカスタマイズしていこう。
今回のカスタマイズは、すべてコピペで済ませることができる。
子テーマのstyle.cssの場所は、まず管理者画面の左側のサイドバーにある「外観」の中の「テーマエディター」をクリックすると、「テーマの編集」というページを開くことができる。
そして、「Cocoon Child: スタイルシート (style.css)」が表示されていたらOK。もし違うファイルが表示されていたら、テーマファイルバー内から「スタイルシート (style.css)」をクリックしよう。

この画像の画面に辿り着くことが出来ただろうか?
また、テーマファイルバーの最上部に「この子テーマは親テーマ Cocoon のテンプレートを引き継ぎます。」というダイアログが表示されているかも確認しておこう。
基礎のカスタマイズ
デザインやエフェクトをいろいろ変える前にやるべきことがあるので、それを済ませておく。
まずは、こちらのコードを子テーマのstyle.cssに必ずコピペしてほしい。
/*目次の基礎となるカスタマイズ*/
/*ここから*/
/*目次ブロックの横幅の再設定*/
.toc {
width: 100%;
}
.main .toc {
width: 95%;
}
/*目次をrelativeに設定*/
.toc, .sidebar .widget_toc h3, .toc-content ul, .toc-content ul li, .toc-content a {
position: relative;
}
/*見出しリストの表示方式の再設定*/
.toc-content a {
display: block;
}
/*見出しリストのmarginの初期化*/
.toc-content ul li {
margin: 0;
}
/*目次を閉じた時の間隔の再調整*/
.main .toc-content {
overflow: hidden;
}
/*目次のhoverエフェクトの初期化*/
.toc a:hover {
text-decoration: none;
}
/*ここまで*/
それでは、このコードで行った変更点を解説したい。
目次ブロックの横幅の再設定
デフォルトの状態では、目次ブロックの横幅の長さは目次に表示される見出しリストの文字の長さに依存している。つまり、Cocoon側でwidthが設定されていない。
これを、このようなコードで指定する。
.toc {
width: 100%;
}
.main .toc {
width: 95%;
}
そうすると、このように目次が本文記事いっぱいに余裕を持って表示される。

この画像のように、表示されているだろうか?
また、「toc」を100%に設定した理由は、サイドバーにも目次を表示するときのことを考えてである。目次ブロック全体の横幅は100%、その中で本文の記事を表示するmain要素の目次の横幅は95%ということだ。
目次をrelativeに設定
デフォルトでは、positionプロパティは特に指定されていない。
しかし、目次をカスタマイズするにあたって、絶対位置指定した疑似要素を使用する時もあるはずだ。
そのために、目次の各ブロックに「position: relative;」を設定する。
.toc, .sidebar .widget_toc h3, .toc-content ul, .toc-content ul li, .toc-content a {
position: relative;
}
こうすることで、「position: absolute;」を使って目次や目次の見出しリストにアイコンを付けたり、疑似要素の横線で区切ったりすることができるようになった。
見出しリストの表示方式の再設定
デフォルトの状態では、目次の見出しリストに表示されている見出しはinlineで表示されている。つまり、このように見出しの文字自体にカーソルを合わせなければ反応しない。

この見出しリストの文字、つまり「a」要素にdisplayプロパティを設定する。
.toc-content a {
display: block;
}
このように、displayの値をblockに設定することで、a要素がリストの横幅いっぱいに広がって、見出しリストの文字と同じ高さであればカーソルが反応するようになる。

このカスタマイズは、見出しリストの見出しに背景を付けたり、カーソルを合わせた時に影が付いて浮き上がったりするエフェクトを付与するときに見栄えが良くなる。なので、忘れずにやっておこう。
見出しリストのmarginの初期化
デフォルトの状態では、リスト化されているli要素に0.2emのmarginが指定されている。
このままでは横線を入れた時などに、右端で揃わず不格好になってしまうのでそれを修正しよう。
.toc-content ul li {
margin: 0;
}
このように、marginを0に再指定しておこう。
目次を閉じた時の間隔の再調整
Cocoonの目次は、閉じたり開いたりすることができる。
そして、デフォルトの状態では、目次を閉じた時に目次の見出しの上の間隔と下の間隔の長さが合わない。

この画像では、わかりやすいように目次に背景を指定している。このように下の間隔だけ長いのがわかるだろうか?
そして、tocからpaddingとborderを省いた場合はこのように表示されてしまう。

紅白羊羹のようになってしまっているだろう。
この原因はデフォルトで指定済みの、見出しリストを構成しているul要素の「toc-list」とそのli要素のmargin-topによるものである。

この赤枠で示したあたりの「toc-content」内のul要素やli要素の上のmarginがそれぞれ悪さをしていると考えたらいい。目次の見出しリストを非表示にしたとき、toc-contentはvisibilityで非表示にされているだけなので、marginやpaddingはそのまま残るのだ。
この場合は、このCSSコードを打ち込むと解決することができる。
.main .toc-content {
overflow: hidden;
}
このように、要素からあふれた部分の表示を指定する「overflow」プロパティを使い、あふれた部分を隠す値である「hidden」を指定することで解決できる。

このように、見出しリスト内部にかかっていたmarginが非表示になったことで見栄えがスッキリした。
目次のhoverエフェクトの初期化
目次の見出しリストにかかっている疑似クラス「:hover」のエフェクトを初期化する。
デフォルトでは、見出しにカーソルを合わせるとアンダーラインが表示される。これは、text-decorationプロパティでunderlineが値に指定されているからだ。
この場合は、このようにする。
.toc a:hover {
text-decoration: none;
}
text-decorationプロパティの値を「none」で上書きするだけでよい。これでエフェクトの初期化は終わりとなる。
以上が、本格的に外観を弄る前の土台となるカスタマイズとなる。
デザインのカスタマイズ
それでは、先ほどの基礎カスタマイズコードのすぐ下に、デザインをカスタムするコードを書き込んでいこう。すべてコピペだけでよい。
線で区切るデザイン
見出しを棒線と点線で区切って、階層をわかりやすくするデザイン。
/*目次のデザインのカスタマイズ(タイプ:線で区切る)*/
/*ここから*/
.main .toc {
padding: 0;
border-radius: 2px;
overflow: hidden;
}
.toc-title {
padding: 8px 10px 9px;
background-color: #ccc;
color: #fff;
font-size: 1.3em;
font-weight: 600;
}
.toc-title::after {
font-weight: 400;
}
.main .toc-content > ul {
margin-bottom: 1.6em;
padding: 0 12px;
}
.toc-content > ul > li {
padding: 0 0 0 10px;
}
.toc-content a {
margin: 3px 0;
padding: 4px 12px;
}
.toc-content a:hover {
font-weight: 600;
}
/*下線部分*/
.toc-content > ul > li::after, .toc-content > ul > li ul::before, .toc-content > ul > li > ul li::after {
position: absolute;
content: '';
left: 0;
width: 100%;
height: 1px;
}
.toc-content > ul > li::after {
bottom: -2px;
background-color: #ccc;
}
.toc-content > ul > li ul::before {
top: -2px;
background-color: transparent;
border-top: 1px dashed #ccc;
}
.toc-content > ul > li > ul li::after {
bottom: -2px;
background-color: transparent;
border-bottom: 1px dashed #ccc;
}
.toc-content > ul > li:last-child::after, .toc-content > ul > li > ul li:last-child::after {
content: none;
}
/*ここまで*/
まずは、カスタマイズのチュートリアル的なデザインを紹介した。
あまり飾り気はないが、そのぶん背景や文字の色を変えるだけでどんなWebサイトにも合うだろう。
アイコンを付けるデザイン
目次の見出し、そして見出しリストの見出しにFont Awesomeのアイコンを付けるデザイン。
/*目次のデザインのカスタマイズ(タイプ:アイコン)*/
/*ここから*/
.toc, .sidebar .widget_toc {
background-color: #B4C8FA;
border: 0;
border-radius: 2px;
overflow: hidden;
}
.main .toc, .sidebar .toc-content {
font-size: 18px;
}
.sidebar .widget_toc {
margin: 16px 0 1em;
}
.main .toc {
padding: 0;
}
.toc-title, .sidebar .widget_toc h3 {
padding: 13px 12px 12px;
background-color: #99B2F1;
color: #fff;
}
.toc-title {
padding-left: 3.3em;
font-size: 1.4em;
font-weight: 600;
text-align: left;
}
.sidebar .widget_toc h3 {
margin: 0;
padding-left: 3.5em;
border-radius: 0;
}
.sidebar .widget_toc .toc {
margin: 0;
}
.main .toc-content > ul {
margin: 1.1em;
margin-top: 0.5em;
}
.toc .toc-content > ul > li > ul {
padding-left: 1.75em;
}
.toc .toc-content > ul > li > ul > li > ul {
padding-left: 1.55em;
}
.toc .toc-content > ul > li > ul > li > ul > li > ul {
padding-left: 1.45em;
}
.toc .toc-content > ul > li > ul > li > ul > li > ul > li > ul {
padding-left: 1.15em;
}
.toc-content a {
padding: 4px;
color: #fff;
font-weight: 600;
letter-spacing: 1px;
}
.toc-content a:hover {
box-shadow: 0px 1px 4px 1px rgba(0,0,0,0.3), 0px 0px 4px 1px rgba(0,0,0,0.3);
}
.toc-content > ul > li > a {
padding-top: 6px;
font-size: 1.1em;
padding-left: 2.1em;
}
.toc-content > ul > li > ul > li > a {
padding-top: 5px;
font-size: 1em;
padding-left: 2em;
}
.toc-content > ul > li > ul > li > ul > li > a {
font-size: 0.9em;
padding-left: 2em;
}
.toc-content > ul > li > ul > li > ul > li > ul li a {
font-size: 0.8em;
padding-left: 2em;
}
/*アイコン管理*/
.main .toc::before, .sidebar .widget_toc h3::before {
position: absolute;
content: '';
top: 0;
left: 0;
background-color: #fff;
border-radius: 50%;
}
.main .toc::before {
height: 48px;
width: 48px;
margin-top: 0.6em;
margin-left: 1em;
}
.sidebar .widget_toc h3::before {
height: 42px;
width: 42px;
margin-top: 0.5em;
margin-left: 0.7em;
}
.main .toc::after, .sidebar .widget_toc h3::after, .toc-content a::after {
position: absolute;
top: 0;
left: 0;
color: #fff;
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
.main .toc::after, .sidebar .widget_toc h3::after {
content: '\f0ca';
color: #C0CEF1;
}
.main .toc::after {
margin-top: 0.5em;
margin-left: 1.2em;
font-size: 1.4em;
}
.sidebar .widget_toc h3::after {
margin-top: 0.66em;
margin-left: 1.2em;
}
.toc-content > ul > li > a::after {
content: '\f02d';
margin-top: 0.24em;
margin-left: 0.6em;
}
.toc-content > ul > li > ul > li a::after {
content: '\f02e';
}
.toc-content > ul > li > ul > li > a::after {
margin-top: 0.25em;
margin-left: 0.65em;
}
.toc-content > ul > li > ul > li > ul > li > a::after {
margin-top: 0.25em;
margin-left: 0.7em;
}
.toc-content > ul > li > ul > li > ul > li > ul li a::after {
margin-top: 0.3em;
margin-left: 0.7em;
}
/*画面サイズが1023px以下の時の調節(モバイルメニュー時)*/
@media screen and (max-width: 1023px) {
.sidebar .widget_toc h3::before {
margin-top: 0.3em;
}
.sidebar .widget_toc h3::after {
margin-top: 0.6em;
margin-left: 1.2em;
}
}
/*画面サイズがスマホの時の調節*/
@media screen and (max-width: 480px){
.main .toc, .sidebar .toc-content {
font-size: 16px;
}
.main .toc::before {
height: 47px;
width: 47px;
margin-top: 0.55em;
margin-left: 0.95em;
}
.main .toc::after {
margin-top: 0.55em;
margin-left: 1.26em;
}
.sidebar .widget_toc h3::before {
height: 39px;
width: 39px;
margin-top: 0.35em;
margin-left: 0.8em;
}
.sidebar .widget_toc h3::after {
margin-top: 0.67em;
margin-left: 1.3em;
}
}
/*ここまで*/
アイコンはFont Awesomeのものを使用した。
いろいろ探してみるのもいいかもしれない。
このデザインは、最近流行りのフラットデザインを目標に作成した。
背景色を変えるだけで、どんなWebサイトにも対応するデザインになったと思う。
最後に
今回のカスタマイズは、Cocoonに用意されている設定と子テーマのstyle.cssを弄るだけなので、特に大きな問題は起きない。
ただ、Cocoon側で大規模なアップデートがあり、目次のクラス名が変わってしまう可能性も0ではないので気を付けてほしい。
これで、目次のカスタマイズの紹介は終わりである。
今回この記事を執筆するにあたって、自分が今まで目次に行っていたCSSコードを見直す良い機会となった。少々冗長なコードにしていたことに気が付くことが出来たからだ。
この記事が役に立つと嬉しい。