CSS で見出し(h1, h2, …)に連番を付ける

検索すると似たようなタイトルでたくさんの記事が見つかります。今さら……な話題ですが、それらを参考に試行錯誤して、次のような CSS になりました。

よく見かける例だと、それぞれの見出しでひとつ下の階層のカウンターだけをリセットしているのが多いのですが、それだと h2 の次に(h3 がなくて) h4 が来るような場合にうまくいきません。そういう文書が悪いとも言えますが。

Chrome と Firefox で異なる結果になったりして、結局こうなりました。counter-set を紹介している記事はほとんど見かけません。見つけたのはこの質問と回答くらいで、回答者が仕様を説明してくれているのはとても参考になりました。仕様の EXAMPLE 22 は Firefox では正しく再現されません。

【2022年4月18日追記】現時点での Safari や iOS 上のブラウザー(Webkit)では counter-set が実装されていないため、下記ではうまくいかないようです。【追記終わり】【2023年12月12日追記】Safari や iOS 上のブラウザー(Webkit)に counter-set が実装されたようです。現時点でまだ実際に動作を確認していませんが。【追記終わり】

padding で字下げをしています。番号の書式は「公用文作成の考え方」を参考にしました。\a0 (non-breaking space)をいくつか入れているのは、連番をカタカナとしたので、見出しそのものの内容がカタカナで始まっている場合にある程度あいだが開いていないと混乱するからです。

body {
    counter-reset: chapter section subsection subsubsection paragraph subparagraph;
}

h1 {
    counter-set: section subsection subsubsection paragraph subparagraph;
}
h2 {
    counter-set: subsection subsubsection paragraph subparagraph;
    padding-left:1em;
}
h3 {
    counter-set: subsubsection paragraph subparagraph;
    padding-left:2em;
}
h4 {
    counter-set: paragraph subparagraph;
    padding-left:4em;
}
h5 {
    counter-set: subparagraph;
}

h1::before {
    counter-increment: chapter;
    content: counter(chapter, upper-roman) "\a0\a0\a0\a0";
}
h2::before {
    counter-increment: section;
    content: counter(section, decimal) "\a0\a0\a0\a0";
}
h3::before {
    counter-increment: subsection;
    content: "(" counter(subsection, decimal) ")\a0\a0\a0";
}
h4::before {
    counter-increment: subsubsection;
    content: counter(subsubsection, katakana) "\a0\a0\a0\a0";
}
h5::before {
    counter-increment: paragraph;
    content: "(" counter(paragraph, katakana) ")\a0\a0\a0";
}
h6::before {
    counter-increment: subparagraph;
    content: counter(subparagraph, upper-alpha) "\a0\a0\a0\a0";
}

きっかけは Markdown でした。最近、Firefox なら拡張機能 Markdown Viewer Webext 、Chrome なら拡張機能 Markdown Preview Plus などを使って、手元で Markdown で書いたものをブラウザーで眺めることがしばしばあります。その際に、この文書は見出しに連番がほしいよなあなどと思ったのです。

ここに挙げた2つの拡張機能は CSS を追加できるので、そこにこれを書いてもいいですが、そうすると Markdown なら全て連番付き見出しになってしまいます。拡張機能 Stylus で、好きなときに入れたり切ったりすることにしました。もちろん Markdown のプレビューだけではなく、あらゆるサイトを見る際に適用できます。

コメントをどうぞ