質問: HTMLで番号付きの見出しを実現する良い方法を教えてください。例えば,次のような文章を作成したいです。 (例1) ``` 1. 漫画の定義 (本文) 2. 漫画の歴史 1. 近代以前 (本文) 2. 現代 (本文) 3. 漫画の役割 1. 娯楽 (本文) 2. 教育 (本文) ``` (例2) ``` 1. 漫画の定義 (本文) 2. 漫画の歴史 2-1. 近代以前 (本文) 2-2. 現代 (本文) 3. 漫画の役割 3-1. 娯楽 (本文) 3-2. 教育 (本文) ``` 私は,このような文章をHTMLにより実現する方法を,3つ考えました。 1つ目は,``‐``要素の内容に,番号を直接書く方法です。例えば,`1. 漫画の定義`と書きます。この方法は,HTMLだけで(例1)にも(例2)にも簡単に対応できるのがメリットです。しかし,見出しの番号を文章構造として表せていないことと,見出しの削除・挿入のたびに番号を更新する必要があることが気に入りません。 2つ目は,``要素を使う方法です。文章全体を``タグで覆ったうえで,例えば`漫画の歴史(本文)`などと書きます。この方法は,見出しの番号を文章構造として表せるうえ,見出しの削除・挿入のたびに番号を更新する必要がないのがメリットです。しかし,私の知る限りでは,CSSのcounterを使わないと(例2)に対応できないことが気に入りません。また,最も外側の``要素が大きくなりすぎることが,お行儀に反しないか,レンダリングパフォーマンスを悪化させないかという不安があります。 3つ目は,``要素を使わずに,``‐``要素にCSSのcounterを直接適用する方法です。この方法は,2つ目の方法よりもシンプルに(例2)に対応できます。しかし,見出しの番号を文章構造として表せていないことが気に入りません。 そこで,この3つの方法の改良案や,あるいはまったく異なるアプローチなどをお聞かせください。できれば,見出しだけでなく,見出し番号もHTMLの文章構造として表したいです。また,なるべくCSSには頼りたくないです。特に,(例2)をスマートに実現できたらすばらしいと思います。
回答: 私でしたら `dl>dd>dl>dd` の2重構造で構造化して 質問のコメントにあるようにCSSのCounterを利用して最初の数字の「装飾」をします。 なぜなら 質問にある文章は説明リストであり、タイトルと本文があること、リストで入れ子で定義できるからです。 また、「2.1」とか「2-1」は「文書構造」という認識ではなくて、あくまで「装飾」です。 どのように表現されるかはCSS次第ということで、構造的にはdlが入れ子で構造化されていれば十分だととらえます。 ``` dl { counter-reset: section; list-style-type: none; } dd:before { counter-increment: section; content: counters(section, ".") "."; } ``` ``` 漫画の定義 (本文) 漫画の歴史 近代以前 (本文) 現代 (本文) ``` コメントでいただいた追記分についての回答 > > 見出しの番号が本文に登場する場合 > > > dl>dd>dl>ddでかつCSSのcounterを利用しない方法でよいかと思います。 hだと5階層までの限界がありますし、見出しの数字(1~5)を間違えないように管理するのはちょっと面倒だなと私は考えます。 ただし、コメントにあるように本文の採番が変わる(つまりはデータ構造が変わる)ときにHTMLの文書構造も変える必要があります。 HTMLの構造的な作りを維持したいのであれば、本文のデータ構造の変更に追随してHTMLの構造も変えるべきです。 別に構造的なつくりを維持しなくてよいのであれば、divでもべた書きでもspanなどを利用した修飾タグだけで書くこともできるでしょう。 以下に記述することは、 質問ではHTMLとCSSでできることということだったので回答というより別の解決策の提案になりますので、スルーしていただいてもかまいません。 上記のやり方はそれはプレーンなテキストとHTMLだけで構成すると非常に変更するときにコストがかかります。 本来はHTMLのほうで吸収するのではなくてどちらかというとデータ構造を変えるべきです。 静的なコンテンツではなくて、サーバサイド言語とデータ構造を用いた動的コンテンツが得意とする分野です。 本文に持つのではなく例えばDB(RDSやNoSQL)やデータ管理(JSONやXMLやCSV)などを利用して本文とは別で何階層目なのか、どの見出しの下につくのかなど管理し、その構造的に管理されたデータを決まった形でHTMLに落とし込むサーバサイド言語(Ruby、python,php)を開発することで非常に楽な管理ができると思います。