見出しとセクション

4.4.11 見出しとセクション

h1h6 要素と hgroup 要素は見出しです。

セクショニング・コンテンツの要素の中にあるヘッディング・コンテンツの最初の要素は、そのセクションの見出しを表します。その後に続く見出しのうち、ランクが同じか高い見出しは、(暗黙的に)新しいセクションを開始し、低いランクの見出しは、一つ前のセクションの一部をなす暗黙の従属セクションを開始します。いずれの場合も、この要素は、暗黙のセクションの見出しを表します。

一部の要素は、セクショニング・ルートといわれます。blockquote 要素 と td 要素が含まれます。これらの要素は、自分自身のアウトラインを持つことができます。しかし、これらの要素の中にあるセクションと見出しは、祖先のアウトラインに寄与しません。

セクショニング・コンテンツの要素は、常に、その直近の祖先となるセクショニング・ルートか、その直近の祖先となるセクショニング・コンテンツの要素のサブ・セクションと見なされます。他の見出しがどんな暗黙のセクションを生成したとしても、その直近であれば場所は問いません。

次の例では:

<body>
 <h1>Foo</h1>
 <h2>Bar</h2>
 <blockquote>
  <h3>Bla</h3>
 </blockquote>
 <p>Baz</p>
 <h2>Quux</h2>
 <section>
  <h3>Thud</h3>
 </section>
 <p>Grunt</p>
</body>

... その構造は、次のようになります:

  1. Foo (明示的な body セクションの見出しで、"Grunt" 段落を含んでいます。)
    1. Bar (暗黙のセクションを開始する見出しで、ブロックの引用と "Baz" 段落を含んでいます。)
    2. Quux (暗黙のセクションを開始する見出しで、見出し以外のコンテンツはありません。)
    3. Thud (明示的な section セクションの見出し)

section 要素が、どのようにして手前の暗黙のセクションを終了して、後ろの段落 ("Grunt") がトップのランク・レベルに戻るようにしているかに注目してください。

セクションは、あらゆるランクの見出しを含むことができます。しかし、ウェブ制作者は、h1 要素だけを使うか、または、セクションのネスト・レベルに合ったランクの要素を使うことが、強く推奨されます。

ウェブ制作者は、また、セクショニング・コンテンツの要素の中にセクションを明示的に包含することが推奨されます。一つのセクショニング・コンテンツ要素の中に複数の見出しを入れ、それによって暗黙に生成されたセクションに依存するのではありません。

例えば、次は正しい例です:

<body>
 <h4>Apples</h4>
 <p>Apples are fruit.</p>
 <section>
  <h2>Taste</h2>
  <p>They taste lovely.</p>
  <h6>Sweet</h6>
  <p>Red apples are sweeter than green ones.</p>
  <h1>Color</h1>
  <p>Apples come in various colors.</p>
 </section>
</body>

しかし、次の方が、同じドキュメントを明確に表現しているでしょう:

<body>
 <h1>Apples</h1>
 <p>Apples are fruit.</p>
 <section>
  <h2>Taste</h2>
  <p>They taste lovely.</p>
  <section>
   <h3>Sweet</h3>
   <p>Red apples are sweeter than green ones.</p>
  </section>
 </section>
 <section>
  <h2>Color</h2>
  <p>Apples come in various colors.</p>
 </section>
</body>

前述のドキュメントのどちらも意味的には同じで、準拠ユーザーエージェントでは同じアウトラインを生成するでしょう。

この 3 つ目の例も、意味的には同じですが、よりメンテナンスが楽になるでしょう(例えば、執筆時に、たびたびセクションを前後に移動させたい場合など):

<body>
 <h1>Apples</h1>
 <p>Apples are fruit.</p>
 <section>
  <h1>Taste</h1>
  <p>They taste lovely.</p>
  <section>
   <h1>Sweet</h1>
   <p>Red apples are sweeter than green ones.</p>
  </section>
 </section>
 <section>
  <h1>Color</h1>
  <p>Apples come in various colors.</p>
 </section>
</body>
4.4.11.1 アウトラインの生成

このセクションでは、セクショニング・コンテンツセクショニング・ルートのアウトラインを生成するアルゴリズムを定義します。このアルゴリズムは、DOM ツリーのノードに入ったり出ていったりしながら、それぞれのノードをツリー順に走査していくという観点で定義されます。

セクショニング・コンテンツ要素やセクショニング・ルート要素のアウトラインは、一つ以上の潜在的にネストしたセクションのリストから構成されます。セクションとは、本来の DOM ツリーのいくつかのノードに相当するコンテナのことです。各セクションは、それに結びづけられた見出しをひとつ持つことができます。そして、さらに多くのネストしたセクションを含むことができます。 アウトラインに対して、このアルゴリズムはまた、DOMツリー内の各ノードを、特定のセクションおよび潜在的な見出しと結びづけます。(アウトラインの中のセクションとは、section 要素に相当するものもあるかもしれませんが、section 要素のことではありません。これらは、ただ単に概念上のセクションでしかありません。)

次のマークアップでは:

<body>
 <h1>A</h1>
 <p>B</p>
 <h2>C</h2>
 <p>D</p>
 <h2>E</h2>
 <p>F</p>
</body>

... 次に示すアウトラインが、body ノード(ゆえにドキュメント全体)に対して生成されることになります:

  1. body ノードに対して生成されたセクション

    見出し "A" と結び付けらる。

    また、段落 "B" とも結びづけられる。

    ネストしたセクション:

    1. 最初の h2 要素の暗黙のセクション

      見出し "C" と結びづけられる。

      また、段落 "D" とも結びづけられる。

      ネストされたセクションはなし

    2. 二番目の h2 要素の暗黙のセクション

      見出し "E" と結び付けられる

      また、段落 "F" とも結びづけられる。

      ネストされたセクションはなし

セクショニング・コンテンツ要素やセクショニング・ルート要素をルートとしている DOM サブツリーの走査では、次のアルゴリズムに従って、その要素のアウトラインを決定しなければいけません:

  1. current outlinee を null とします。(アウトライン生成中の要素をホールドします)

  2. current section を null とします。(DOM 内の要素がすべてセクションと結びつくことができるよう、セクションへのポインターをホールドします)

  3. 要素をホールドするためにスタックを生成します。それは、ネストを扱うために使われます。このスタックを空に初期化します。

  4. ツリー順に DOM を走査しているあいだ、あなたが出入りするときの各要素に対して、下記の最初の関連手順を始動します。

    スタックのトップが要素であり、あなたがその要素から出て行くところなら、

    出て行くその要素は、ヘッディング・コンテンツ要素です。

    スタックの最後から、その要素を取り除きます。

    スタックの先頭がヘッディング・コンテンツ要素なら、

    何もしません。

    セクショニング・コンテンツ要素またはセクショニング・ルート要素に入ろうとしているとき

    current outlinee が null でなく、かつ、current section が見出しを持っていなければ、暗黙の見出しを生成し、それを current section の見出しとします。

    current outlinee が null でなければ、current outlinee をスタックの最後に挿入します。

    current outlinee を、これから入ろうとする要素とします。

    current section を、current outlinee 要素に対して新たに生成したセクションとします。

    そのアウトライン内の唯一のセクションとして、先ほどの新規の current section を使って初期化することで、新規の current outlinee が新規のセクションを持つようにします。

    セクショニング・コンテンツ要素から出て行こうとするとき、スタックが空でなければ

    スタックの最後からトップ要素を取り除きます。そして、current outlinee をその要素となるようにします。

    current section を、current outlinee 要素のアウトラインの中の最後のセクションとします。

    これから出て行くセクショニング・コンテンツ要素のアウトラインを、current section に追加します。(これは、どのセクションがそのアウトラインの最後のセクションとなるのかを変更しません。)

    セクショニング・ルート要素から出て行こうとするとき、スタックが空でなければ

    次の手順を実行します:

    1. スタックの最後からトップ要素を取り除き、current outlinee をその要素とします。

    2. current section を、current outlinee 要素のアウトライン内にある最後のセクションとします。

    3. 最も深い子の探査:もし current section の子にセクションがなければ、これらの手順を中止します。

    4. current section を、現在の current section の最後の子セクションとします。

    5. 最も深い子の探査」の手順に戻ります。

    セクショニング・コンテンツ要素またはセクショニング・ルート要素から出て行こうとするとき

    current outlinee が、これから出ていこうとする要素となります。

    current section を、current outlinee 要素のアウトライン内の最初のセクションとします。

    手順全体における次の手順にスキップします。(走査は終了です。)

    current outlinee が null であれば

    何もしません。

    ヘッディング・コンテンツ要素に入ろうとするとき

    current section が見出しを持っていなければ、入ろうとしているその要素を、current section に対する見出しとします。

    そうでなければ、もし、入ろうとしているその要素のランクが、current outlineeアウトラインの最後のセクションの見出しのランクと同じか上なら、新しいセクションを生成し、current outlinee 要素のアウトラインにそれを加えることで、この新しいセクションが、そのアウトラインの新しい最後のセクションとなるようにします。current section を、その新しいセクションとします。これから入ろうとしているその要素を、current section に対する新しい見出しとします。

    そうでなければ、次の手順を実行します:

    1. candidate section を、current section とします。

    2. もし、これから入ろうとする要素のランクが、candidate section の見出しのランクより低ければ、新しいセクションを生成し、candidate section にそれを加えます。(これは、どのセクションがアウトラインの最後のセクションになるかを変更しません。)current section を、この新しいセクションとします。これから入ろうとするその要素を、current section に対する新たな見出しとします。これらの手順を中止します。

    3. new candidate section を、current outlineeアウトラインの中で candidate section を含むセクションとします。

    4. candidate section を、new candidate section とします。

    5. 手順 2 に戻ります。

    これから入ろうとするその要素を、スタックの最後に加えます。(これによって、アルゴリズムはその要素の子孫すべてをスキップすることになります。)

    h1 は最も高いランクを持ち、h6 は最も低いランクを持つことを思い出してください。

    そうでなければ

    何もしません。

    さらに、ノードを出るときはいつでも、上記の手順を実行した後、current section が null でなければ、セクションを持つそのノードを current section と結びづけます。

  5. current outlinee が null なら、DOM の中には、セクショニング・コンテンツ要素もセクショニング・ルート要素もありません。アウトラインがないのです。これらの手順を中止します。

  6. 前述の手順でセクションと結びづけられなかったあらゆるノードを、それらのセクションとして current outlinee と結びづけます。

  7. もしあれば、すべてのノードを、それらが結びづけられているセクションの見出しと結びづけます。

  8. current outlineebody 要素なら、その要素に対して生成されたアウトラインは、ドキュメント全体のアウトラインとなります。

前述のアルゴリズムで生成されたセクションのツリー、または、それにまつわるサブセットは、ドキュメントのアウトラインを生成する場合に使われなければいけません。例えば、目次を生成する場合などです。

対話型の目次を生成するとき、その目次のエントリは、オリジナルのドキュメント内の実在する要素に対してセクションが生成されたなら、対応するセクショニング・コンテンツ要素にユーザーをジャンプさせるべきです。もしくは、ツリー内のセクションが上記の処理で見出しに対して生成されたなら、対応するヘッディング・コンテンツ要素にジャンプさせるべきです。

それゆえに、body 内の最初のヘッダーがどこで見つかろうとも、ドキュメントの最初のセクションの選択は、常に、ドキュメントのトップにユーザーを連れて行きます。

セクション section と関連付けられたヘッディング・コンテンツ要素のアウトライン深度は、section の祖先である セクションの数に、1 をプラスしたものです。セクションと関連付けられていないヘッディング・コンテンツ要素のアウトライン深度は 1 です。

ユーザーエージェントは、明示的なセクションの見出しがないセクションに対して、デフォルトの見出しを提供するべきです。

次の抜粋を考えてみましょう:

<body>
 <nav>
  <p><a href="/">Home</a></p>
 </nav>
 <p>Hello world.</p>
 <aside>
  <p>My cat is cute.</p>
 </aside>
</body>

これには見出しがありませんが、3 つのセクションがあります:ドキュメント(body)と 2 つのサブ・セクション(navaside)です。ユーザーエージェントは次のようにアウトラインを提供することができるでしょう:

  1. Untitled document
    1. Navigation
    2. Sidebar

これらのデフォルトの見出し("Untitled document", "Navigation", "Sidebar")は、この仕様で指定しません。これは、ユーザーの言語、ページの言語、ユーザーの設定、ユーザーエージェント実装者の設定によって違ってくるでしょう。

次の JavaScript 関数は、ツリー走査の実装方法を示したものです。引数 root は、走査するツリーのルートです。引数 enter と exit は、それぞれ、それらの出入りするときのノードを使って呼び出されるコールバックです。[ECMA262]

function (root, enter, exit) {
  var node = root;
  start: while (node) {
    enter(node);
    if (node.firstChild) {
      node = node.firstChild;
      continue start;
    }
    while (node) {
      exit(node);
      if (node.nextSibling) {
        node = node.nextSibling;
        continue start;
      }
      if (node == root)
        node = null;
      else
        node = node.parentNode;
    }
  }
}

※ 原文:http://www.w3.org/TR/2011/WD-html5-20110525/sections.html#headings-and-sections