Cocoonの目次のカスタマイズ

Cocoon

今回は、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タグまでに制限しよう

こうすることで、目次もゴチャゴチャしなくなる。

私が目次ブロックに表示する見出しはH4タグまでで十分だと思う理由は、見出しは4つと2つに分けることができると考えているからだ。

本文のタイトルであるH1、本文中の章であるH2、章の中の大きな段落であるH3、そして、その段落の中でのリストの役割を持つH4。

このように本文の見出しの役割を取り決めて文章を組み立てていくと、H5とH6はめったに使うことはなく、また使ったとしてもそれはH4内を整えて読みやすくするための補足的な要素でしかない。

つまり、H5とH6を目次に表示しても、実際のところはH4を表示したらそれでいいはずなので、H5以降の見出しタグを目次に表示することにあまり意味はない気がするからだ。

なので、目次の表示数もH4までにすることを推奨した。


これらを設定しなおし「変更をまとめて保存」ボタンを押そう。設定が変更されていることを確認したら完了となる。

これでカスタマイズをする前の設定の解説を終える。

子テーマのstyle.cssで目次をカスタマイズ

それでは、子テーマのstyle.cssにcssコードを入力して目次をカスタマイズしていこう。

今回のカスタマイズは、すべてコピペで済ませることができる。

子テーマのstyle.cssの場所は、まず管理者画面の左側のサイドバーにある「外観」の中の「テーマエディターをクリックすると、「テーマの編集」というページを開くことができる。

そして、「Cocoon Child: スタイルシート (style.css)」が表示されていたらOK。もし違うファイルが表示されていたら、テーマファイルバー内から「スタイルシート (style.css)」をクリックしよう。

この画像の画面に辿り着くことが出来ただろうか?

また、テーマファイルバーの最上部に「この子テーマは親テーマ Cocoon のテンプレートを引き継ぎます。」というダイアログが表示されているかも確認しておこう。

この記事で紹介するカスタマイズは、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%ということだ。

widthの単位を「%(パーセント)」に設定したのは、レスポンシブによるスマートフォンの画面での表示を考えてのことである。

表示する横幅の長さは、だいたい100%から80%の間までがちょうどいいサイズで表示されるだろう。メディアクエリを用いて画面サイズが480px以下の時を調節するのなら50%でもいいかもしれないが、AMPの場合を考慮するとCSSの容量は軽いに越したことはないので、今回は95%で統一した。

目次をrelativeに設定

デフォルトでは、positionプロパティは特に指定されていない

しかし、目次をカスタマイズするにあたって、絶対位置指定した疑似要素を使用する時もあるはずだ。

そのために、目次の各ブロックに「position: relative;」を設定する

目次を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が指定されている

このままでは横線を入れた時などに、右端で揃わず不格好になってしまうのでそれを修正しよう。

見出しリストの見出しの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が非表示になったことで見栄えがスッキリした。

なぜ「toc-content」に「overflow: hidden;」を指定するとこうなるのかの解説を書き留めておく。

そもそもの話、目次は見出しリストが非表示の状態がニュートラルとなっている。

そして、目次の見出しリストが非表示になっているとき、toc-contentは「height: 0;」に指定されている。つまり、要素の高さがゼロならば要素は表示されなくなる。表示できる縦の面積が確保されていないからだ。

しかし、要素の中の要素のmarginやpaddingは残り続ける。つまり、縦の面積が0pxの要素から、内部の要素の間隔がはみ出した状態となっている

なので、そのあふれた部分を見えなくすることで綺麗に解決することができるわけだ。

目次のhoverエフェクトの初期化

目次の見出しリストにかかっている疑似クラス「:hover」のエフェクトを初期化する

デフォルトでは、見出しにカーソルを合わせるとアンダーラインが表示される。これは、text-decorationプロパティでunderlineが値に指定されているからだ。

この場合は、このようにする。

目次のhoverエフェクトの初期化
.toc a:hover {
	text-decoration: none;
}

text-decorationプロパティの値を「none」で上書きするだけでよい。これでエフェクトの初期化は終わりとなる。


以上が、本格的に外観を弄る前の土台となるカスタマイズとなる。

デザインのカスタマイズ

それでは、先ほどの基礎カスタマイズコードのすぐ下に、デザインをカスタムするコードを書き込んでいこう。すべてコピペだけでよい。

CSSは「下に書いたものが上に書いたものを上書きする」というルールなので、基礎のコードの下にデザインのコードという順番を必ず守ってほしい。

線で区切るデザイン

見出しを棒線と点線で区切って、階層をわかりやすくするデザイン。

目次を線で区切るデザインのCSSコード
/*目次のデザインのカスタマイズ(タイプ:線で区切る)*/
/*ここから*/
.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サイトのデザインに合わせてやってほしい。

カスタマイズ解説
  • 最初に、見出し全体にかかっていたpaddingを0にする
    そして、目次に微妙な柔らかさを持たせるためにborde-radiusを2pxほど丸める。その際、目次の見出しの角が突っ張ってしまうので、over-flow:hiddenで目次から飛び出した角を隠す
  • タイトルのpaddingが上と下とで長さが違うのは、文字自体にかかっているline-heightがあるから。なのでtopを1pxだけ大きくした。
    あとは背景の色を変えたり、文字の大きさや太さを変えたりなどした。
  • H2見出しのグループの区切りには疑似要素を使用した。このとき、子結合子である「>」を使って、一番上の「ul li」要素だけを指定する必要がある。
    また、最後の見出しグループには区切りを入れる必要は無いため、疑似要素に疑似クラス「:last-child」を使用した。
  • また、H2見出しグループ内のH3以下の見出しの区切りにも同じく疑似要素を使用する
  • 最後に、カーソルを合わせた時に見出しの文字が太くなるエフェクトを疑似クラス:hoverを使ってかけた。

疑似要素にも疑似クラスを使うことができる

そのときは、「:疑似クラス::疑似要素」と表記するので間違わないようにしよう。

疑似クラスがかかった要素疑似要素」だと覚えたらよい。

メモがてらに付け加えて解説しておくことがある。

.main .toc-content > ul {
	margin-bottom: 1.6em;
}

このように、見出しリストの一番上のul要素の下のmarginを0.6emぶん多めに取っているのは、目次を開いているときに目次リスト全体の上下の間隔を合わせるためである。

目次を閉じるとき、目次の見出しリストを上に縮めて収納するアニメーションの原理はこのようになっている。

.toc-checkbox:checked~.toc-content {
	padding-top: .6em;
}

このように、「見出しのチェックボックスにチェックが入っているときは、見出しコンテンツの上の間隔を0.6emだけ空けますよ」と指定されている。そして、このチェックが外れた時に0.6emが少しだけ時間をおいて消えることで、上に縮む表現を自然に表現しているのだ。

なので、見出しリスト全体のul要素の下のmarginに0.6emぶん足すことで、目次が展開されているときに見出しリストの上下の間隔の釣り合いを取った。


また、全体のmarginをemで指定し、そこからmargin-topの値を0.6em引いた数値で再指定する方法もある

.main .toc-content > ul {
	margin: 1em;
	margin-top: 0.4em;
}

こちらは、見出しリスト全体のul要素の上のmarginを0.6emぶん引くことで釣り合いをとる方法となる。

こちらのほうが簡単かもしれない。

まずは、カスタマイズのチュートリアル的なデザインを紹介した。

あまり飾り気はないが、そのぶん背景や文字の色を変えるだけでどんなWebサイトにも合うだろう。

アイコンを付けるデザイン

目次の見出し、そして見出しリストの見出しにFont Awesomeのアイコンを付けるデザイン。

目次にアイコンを付けたデザインのCSSコード
/*目次のデザインのカスタマイズ(タイプ:アイコン)*/
/*ここから*/
.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;
	}
}
/*ここまで*/

このCSSコードでは、外観はこのようになる。

見出しにカーソルを合わせた時は、見出しに影が付いてまるで浮き上がっているように見える。

目次を閉じた時はこうなる。

サイドバーに表示する場合も考慮に入れた。

上下のウィジェットとの間隔の微調整や、既にサイドバー見出しにアイコンを表示している場合の調整などは、各自でやってほしい。

アイコンはFont Awesomeのものを使用した。

いろいろ探してみるのもいいかもしれない。

カスタマイズ解説
  • このカスタマイズでは、アイコンや疑似要素を多用する。そのため、最初に目次要素全体の文字の大きさを「px」で指定し、その後で文字やアイコンの大きさや間隔などを「em」で指定する。
    この理由は、のちほど詳しく説明する。
  • H2見出し・H3見出し・H4見出し・H5とH6見出しで、文字の大きさを0.1em単位で変える
    見出しリストにメリハリをつけるためである。
  • アイコンや疑似要素の位置を左上に固定するため、topとleftを0に指定する
    そして、margin-topとmargin-leftを使って位置を調整する。その際、単位はemを使う。
  • 目次の見出しのアイコンを目立たせるため、「::before」を使ってコースターのような円状の要素を作成する。
    このとき「toc-title」要素では、既に「.toc-title::after」で「開く・閉じる」を使っているため、疑似要素同士を重ね合わせることができない。
    なので「.main .toc::before」で白い円を、「.main .toc::after」でアイコンを表示した。
  • コードの容量を少なくするため、共通している部分をまとめる。
    疑似要素の「position: absolute;」などがそれである。
  • 見出しを選んだ時のエフェクトは、「box-shadow」を使用した
    いろいろ選択肢は思い浮かんだが、この目次のデザインではこれが一番インパクトがあって、強調しているイメージも強そうな気がしたからだ。

本文に表示する目次とサイドバーの見出し要素の文字の大きさを「18px」に、画面サイズが480pxの場合は「16px」と指定している。

この理由は、文字とアイコンのサイズや、アイコンと要素の内側からの距離などを、すべて「em」という単位で指定するためだ。

「em」とは要素に設定された文字サイズからの相対的な大きさや距離を表す単位である。この単位の利点は、スマホやタブレット、PCなどの様々な画面サイズへの対応力が高い。つまり短いコードで簡単にレスポンシブにできるため、style.cssの省エネ化に繋がるというわけだ。

このデザインは、最近流行りのフラットデザインを目標に作成した。

背景色を変えるだけで、どんなWebサイトにも対応するデザインになったと思う。

最後に

今回のカスタマイズは、Cocoonに用意されている設定と子テーマのstyle.cssを弄るだけなので、特に大きな問題は起きない。

ただ、Cocoon側で大規模なアップデートがあり、目次のクラス名が変わってしまう可能性も0ではないので気を付けてほしい。


これで、目次のカスタマイズの紹介は終わりである。

今回この記事を執筆するにあたって、自分が今まで目次に行っていたCSSコードを見直す良い機会となった。少々冗長なコードにしていたことに気が付くことが出来たからだ。

この記事が役に立つと嬉しい。