書籍目次用 counter-increment
「Yahoo! 知恵袋」で(リアル)書籍の目次用として次のような仕様で目次を作れないかという質問があった。
- ♘♘♘♘♘♘♘♘♘♘1
- ◇◇◇◇◇◇◇2
- ●●●●●●●●●●10
- ✤✤✤✤✤✤✤✤15
- □□□□□□□□□16
- ○○○○○○○25
- 章や節の番号、題、開始ページ番号を付ける。
- 開始頁は右端で右揃え。
- 節は数文字分インデント。
- 章や節の右にページ部分の前まで点線を付ける。
- 点線の長さは不定。
質問者さんは章や節の番号を文字で入力することを考えていたが、私は counter-increment プロパティを利用することを思いついた。番号を漢数字にするには何かやり方があるはずなので、ネット検索。
難しかったのが、長さ不定の点線。ネット検索したらここはグラデーションを付ける linear-gradient プロパティの兄弟 repeating-linear-gradient と flex-grow: 1 で実現できるとわかった。そこまでできれば flexbox の justify-content: space-between でなんとかなる。
- ● CSS
-
- ol.toc2 {margin: 10px; padding: 0;}
- .toc2 > li {margin-inline: 0; padding: 0; list-style-type: none; counter-increment: chapter;}
- .toc2 > li > div {display: flex; justify-content: space-between; column-gap: 5px; align-items: center;}
- span.dashed_h-line {content: ""; margin-left: 0.3em; flex-grow: 1; background-image: repeating-linear-gradient(90deg,black 97%,white); height: 2px;}
- span.chapt::before {content: "第"counter(chapter,cjk-ideographic)"章 ";}
- span.start-page {width: 40px; text-align: right;}
- ol.inner-toc {padding-left: 2em;}
- .inner-toc > li {display: flex; justify-content: space-between; column-gap: 5px; align-items: center; counter-increment: sec;}
- .inner-toc > li::before {content: "第" counter(sec,cjk-ideographic) "節";}
- ● HTML
-
- <ol class="toc2">
- <li><div>
<span class="chapt">
♘♘♘♘♘♘♘♘♘♘</span>
<span class="dashed_h-line"></span>
<span class="start-page">1</span>
</div>
<ol class="inner-toc">- <li>◇◇◇◇◇◇◇
<span class="dashed_h-line"></span>
<span class="start-page">2</span></li> - <li>●●●●●●●●●●
<span class="dashed_h-line"></span>
<span class="start-page">10</span></li>
- <li>◇◇◇◇◇◇◇
- </li>
- <li><div>
<span class="chapt">
✤✤✤✤✤✤✤✤</span>
<span class="dashed_h-line"></span>
<span class="start-page">15</span>
</div>
<ol class="inner-toc">- <li>□□□□□□□□□
<span class="dashed_h-line"></span>
<span class="start-page">16</span></li> - <li>○○○○○○○
<span class="dashed_h-line"></span>
<span class="start-page">25</span></li> - </ol>
- <li>□□□□□□□□□
- </li>
- </ul>
counter-increment プロパティの利用
ol/li 要素での番号付リストの場合、text-align: center でセンタリングすると、マーカーとの間に異様な隙間ができてしまう。ul/li 要素での番号なしリストでも同じである。
- テキストテキストテキスト
- テキストテキストテキストテキストテキスト
counter-increment プロパティを使うとその問題を解決できる。数字の前や後ろに文字を付加することも出来る。
ポイントは、
- 準備として li 要素のマーカーを消し、幅(width)を fit-content にしておく。
- counter-increment と counter 関数の値に共通の適当な名前を付ける。ここでは「eel」にしたが、全角文字でも構わない。
- 疑似要素「::before」を利用し、content プロパティの値である counter 関数の前後にダブルクォテーションで括って付加したい文字列を指定する。
- ● CSS
-
- ol.auto-count {padding-left: 1em;}
- .auto-count li {list-style-type: none; width: fit-content;
margin: 2px auto; counter-increment: eel;} - .auto-count li::before {content: "No."counter(eel)": ";}
- ● HTML
-
- <ol class="auto-count">
<li>テキストテキストテキスト</li>
<li>テキストテキストテキストテキストテキストテキスト</li>
<li>テキストテキストテキストテキストテキスト</li>
- </ol>
- <ol class="auto-count">
- テキストテキストテキスト
- テキストテキストテキストテキストテキストテキスト
- テキストテキストテキストテキストテキスト
複合 counter-increment プロパティ
目次での利用を想定して counter-increment プロパティを複合して使えないかと考えた。ネットを検索して二重利用は見つけたが、外側の ol 要素の値を継承して1番目の値とする用法は見つけられなかった。そこでごちゃごちゃやっていたら......成功してしまった(^^;;;
ポイントは、
- 外側のol 要素に対しては、counter-increment プロパティと counter 関数、::before 擬似要素で連番を作成する(「counter-increment プロパティの利用」参照)。
- 内側の ol 要素に対して counter-increment プロパティを2つ定義、1つ目の値を外側のと同値+「0」(数字のゼロ)にする。
- 内側 ol 要素の li::before に対して、「-」を挟んで counter 関数を2つ使用する。
- ● CSS
-
- ol.my-count {padding-left: 1em;}
- .my-count>li {list-style-type: none; counter-increment: bee;}
- .my-count>li::before {content: counter(bee)".";}
- ol.my-count2 li {list-style-type: none; counter-increment: bee 0; counter-increment: snake;}
- .my-count2 li::before {content: counter(bee)"-"counter(snake)". ";}
- ● HTML
-
-
<ol class="my-count">
<li>章題</li>
<li>章題- <ol class="my-count2">
<li>節題</li>
<li>節題</li> - </ol>
- <ol class="my-count2">
<li>章題</li>- </ol>
-
<ol class="my-count">
- 結果
-
- 章題
- 章題
- 節題
- 節題
- 章題
- 結果の表示に関しては、スマホでの表示スペースの都合で counter-increment に関係ないレイアウト系 CSS を追加した。