見出しとセクション

4.3.10 見出しとセクション

h1h6 要素は見出しです。

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

h1h6 要素は、新たなセクションまたは副セクションの見出しを意図していない限り、小見出し、サブタイトル、別表題、タグラインをマークアップするのに使ってはいけません。代わりに、本仕様の専用の要素を使わない共通のイディオムのセクションにあるマークアップパターンを使ってください。

一部の要素は、セクショニング・ルートといわれます。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") がトップレベルに戻るようにしているかに注目してください。

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

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

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

<body>
 <h4>リンゴ</h4>
 <p>リンゴは果物です。</p>
 <section>
  <h2>味</h2>
  <p>それらはとても美味しいです。</p>
  <h6>甘さ</h6>
  <p>赤いリンゴは緑のリンゴより甘いです。</p>
  <h1>色</h1>
  <p>リンゴにはいろいろな色があります。</p>
 </section>
</body>

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

<body>
 <h1>リンゴ</h1>
 <p>リンゴは果物です。</p>
 <section>
  <h2>味</h2>
  <p>それらはとても美味しいです。</p>
  <section>
   <h3>甘さ</h3>
   <p>赤いリンゴは緑のリンゴより甘いです。</p>
  </section>
 </section>
 <section>
  <h2>色</h2>
  <p>リンゴにはいろいろな色があります。</p>
 </section>
</body>

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

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

<body>
 <h1>リンゴ</h1>
 <p>リンゴは果物です。</p>
 <section>
  <h1>味</h1>
  <p>それらはとても美味しいです。</p>
  <section>
   <h1>甘さ</h1>
   <p>赤いリンゴは緑のリンゴより甘いです。</p>
  </section>
 </section>
 <section>
  <h1>色</h1>
  <p>リンゴにはいろいろな色があります。</p>
 </section>
</body>

この最後の例は、古いブラウザーでもうまくレンダリングされるように、明示的なスタイルのルールが必要となるでしょう。CSS をサポートしていない古いブラウザーは、すべての見出しをトップ・レベルの見出しとしてレンダリングするでしょう。

4.3.10.1 アウトラインの生成

現時点では、準拠チェッカーなどのソフトウェアにはこのアウトライン・アルゴリズムが実装されているものの、グラフィカルブラウザーや支援技術のユーザーエージェントで、このアルゴリズムの実装は知られていません。従って、このアウトライン・アルゴリズムを頼りにして、ユーザーにドキュメント構造を伝達することはできません。ウェブ制作者には、見出しランク (h1h6) を使ってドキュメント構造を伝達することが求められます。

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

セクショニング・コンテント要素やセクショニング・ルート要素のアウトラインは、一つ以上の潜在的にネストされたセクションのリストから構成されます。セクションとは、元の DOM ツリーのいくつかのノードに相当するコンテナのことです。各セクションは、それに結びづけられた見出しをひとつ持つことができます。そして、さらに多くのネストされたセクションを含むことができます。 このアウトラインのアルゴリズムはまた、DOMツリー内の各ノードを、特定のセクションおよび潜在的な見出しと結びづけます。(アウトラインの中のセクションとは、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. 2 番目の h2 要素に対する暗黙のセクション

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

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

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

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

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

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

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

  4. ツリー順に DOM を走査します。これは、アウトラインを生成しようとするサブツリーのルートで、セクショニング・コンテント要素やセクショニング・ルート要素から始めます。そして、走査において要素に入ったり出ていったりするときに、それぞれの要素に対して、下記のうち関連する最初の手順を実行します。

    要素を出るとき、その要素がスタックのトップにある要素なら

    出て行こうとする要素は、ヘッディング・コンテント要素か、hidden 属性を伴う要素です。

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

    スタックのトップがヘッディング・コンテント要素か、hidden 属性を伴う要素なら

    何もしません。

    hidden 属性を伴う要素に入るとき

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

    セクショニング・コンテント要素に入るとき

    次の手順を実行します:

    1. current outline target が null でなければ、次の副手順を実行します:

      1. current section が見出しを持たなければ、暗黙的な見出しを生成し、それを current section の見出しとします。

      2. current outline target をスタックの最後に挿入します。

    2. current outline target を、入ろうとしている要素とします。

    3. current section を、current outline target 要素のために新たに生成されたセクションとします。

    4. current outline target を、current section と結び付けます。

    5. 新たな current outline target に対する新たなアウトラインの出来上がりです。このアウトラインにある唯一のセクションとして、新たな current section で初期化されただけの状態です。

    セクショニング・コンテント要素を出るとき、スタックが空でなければ

    次の手順を実行します:

    1. current section に見出しがなければ、暗黙的な見出しを生成し、それを current section に対する見出しとします。

    2. スタックから最初の要素を取り除き、current outline target をその要素とします。

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

    4. 出ようとしているセクショニング・コンテント要素のアウトラインcurrent section に追加します。(これによって、どのセクションがアウトラインの最後のセクションになるのかに関して変更が発生することはありません。)

    セクショニング・ルート要素に入るとき

    次の手順を実行します:

    1. current outline target が null でないなら、current outline target をスタックの最後に挿入します。

    2. current outline target を、入ろうとしている要素とします。

    3. current outline target親のセクションを、current section とします。

    4. current section を、current outline target 要素に対して新たに生成されたセクションとします。

    5. 新たな current outline target に対する新たなアウトラインの出来上がりです。このアウトラインにある唯一のセクションとして、新たな current section で初期化されただけの状態です。

    セクショニング・ルート要素を出るとき、スタックが空でなければ

    次の手順を実行します:

    1. current section に見出しがなければ、暗黙的な見出しを生成し、それを current section の見出しとします。

    2. current section を、current outline target親のセクションとします。

    3. スタックから最初の要素を取り除き、current outline target をその要素とします。

    セクショニング・コンテント要素またはセクショニング・ルート要素を出るとき (スタックが空の場合)

    current outline target は出て行こうとする要素です。そして、それは、アウトラインが生成されようとしているサブツリーのルートで、セクショニング・コンテント要素かセクショニング・ルート要素です。

    current section に見出しがなければ、暗黙的な見出しを生成し、それを current section に対する見出しとします。

    これら手順全体での次の手順にスキップします。(走査は完了です。)

    ヘッディング・コンテント要素に入るとき

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

    そうでなければ、入ろうとする要素のランクが、current outline targetアウトラインの最後のセクションの見出しと同じか高い、または、current outline targetアウトラインの最後のセクションの見出しが暗黙的な見出しなら、新たなセクションを生成し、それを current outline target 要素のアウトラインに追加して、この新たなセクションがそのアウトラインの新たな最後のセクションとなるようにします。current section をその新たなセクションとします。入ろうとする要素を、current section に対する新たな見出しとします。

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

    1. candidate sectioncurrent section とします。

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

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

    4. candidate sectionnew candidate section とします。

    5. 見出しループ」の手順に戻ります。

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

    h1 は最高ランクであり、h6 が最低ランクであることを思い出してください。

    上記に該当しなければ

    何もしません。

    さらに、この走査が一つのノードを出るときは常に、上記の手順を追えた後に、そのノードがまだセクションと結び付けられていないなら、そのノードをセクション current section と結び付けます。

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

この上記アルゴリズムによって生成されたセクションのツリー、または、それに伴うサブセットは、ドキュメントのアウトライン生成時に利用されなければいけません。たとえば、目次を生成するときなどです。

Documentbody 要素に対して生成されるアウトラインは、ドキュメント全体のアウトラインとなります。

インタラクティブな目次を生成するとき、エントリーは、セクションがオリジナルのドキュメントの実在の要素に対して生成されたなら、その関連のセクショニング・コンテント要素へ、また、ツリーのセクションが上記プロセスで見出しに対して生成されたなら、その関連のヘッディング・コンテント要素へ、ユーザーをジャンプさせるべきです。

従って、ドキュメントの最初のセクションを選択するということは、body の最初の見出しがどこで見つかるかにかかわらず、常に、ドキュメントのトップへユーザーを連れて行くことになります。

セクション section と関連付けられたヘッディング・コンテント要素のアウトライン深度は、その Document の要素のアウトラインが生成されるときに、section が見つかる最外縁のアウトラインの中にある section の祖先となるセクションの数に、1 をプラスしたものです。セクションと関連付けられていないヘッディング・コンテント要素のアウトライン深度は 1 です。

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

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

<body>
 <nav>
  <p><a href="/">ホーム</a></p>
 </nav>
 <p>世界よこんにちわ。</p>
 <aside>
  <p>私の猫はかわいい。</p>
 </aside>
</body>

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

  1. Untitled document
    1. Navigation
    2. Sidebar

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

次の JavaScript 関数は、ツリー走査の実装方法を示したものです。引数 root は、走査するツリーのルートです(セクショニング・コンテント要素かセクショニング・ルート要素のいずれか)。引数 enterexit は、それぞれ、それらの出入りするときのノードを使って呼び出されるコールバックです。 [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 == root) {
        node = null;
      } else if (node.nextSibling) {
        node = node.nextSibling;
        continue start;
      } else {
        node = node.parentNode;
      }
    }
  }
}
4.3.10.2 サンプルのアウトライン

このセクションは非規定です。

次のドキュメントに、アウトライン・アルゴリズムを簡単に当てはめてみましょう。このドキュメントは、とても短いセクションと副セクションがある本を表しています:

<!DOCTYPE HTML>
<title>税金ブック (すべて1ページ区切り)</title>
<h1>税金ブック</h1>
<h2>お金を稼ぐ</h2>
<p>お金を稼ぐことは良いことです。</p>
<h3>仕事を得る</h3>
<p>お金を稼ぐなら、普通は仕事が必要です。</p>
<h2>お金を使う</h2>
<p>使うとは、おもにお金が何に使われたのかです。</p>
<h3>安いもの</h3>
<p>安いものを買っても、コスト効率が良いわけではありません。</p>
<h3>高価なもの</h3>
<p>最も高価なものが最もコスト効率が良いわけでもありません。</p>
<h2>お金を投資する</h2>
<p>あなたは他人にあなたのお金を貸すことができます。</p>
<h2>お金を失う</h2>
<p>もしあなたがお金を使ったり投資したりしたら、, いずれあなたはお金を失います。
<h3>浅はかな判断</h3>
<p>あなたがお金を失ったなら、大抵それはあなたがミスを犯したからです。</p>

この本は次のアウトラインを形成するでしょう:

  1. 税金ブック
    1. お金を稼ぐ
      1. 仕事を得る
    2. お金を使う
      1. 安いもの
      2. 高価なもの
    3. お金を投資する
    4. お金を失う
      1. 浅はかな判断

title 要素はアウトラインに加わらない点に注意してください。

Here is a similar document, but this time using section elements to get the same effect:

<!DOCTYPE HTML>
<title>The Tax Book (all in one page)</title>
<h1>The Tax Book</h1>
<section>
 <h1>Earning money</h1>
 <p>Earning money is good.</p>
 <section>
  <h1>Getting a job</h1>
  <p>To earn money you typically need a job.</p>
 </section>
</section>
<section>
 <h1>Spending money</h1>
 <p>Spending is what money is mainly used for.</p>
 <section>
  <h1>Cheap things</h1>
  <p>Buying cheap things often not cost-effective.</p>
 </section>
 <section>
  <h1>Expensive things</h1>
  <p>The most expensive thing is often not the most cost-effective either.</p>
 </section>
</section>
<section>
 <h1>Investing money</h1>
 <p>You can lend your money to other people.</p>
</section>
<section>
 <h1>Losing money</h1>
 <p>If you spend money or invest money, sooner or later you will lose money.
 <section>
  <h1>Poor judgement</h1>
  <p>Usually if you lose money it's because you made a mistake.</p>
 </section>
</section>

This book would form the same outline:

  1. The Tax Book
    1. Earning money
      1. Getting a job
    2. Spending money
      1. Cheap things
      2. Expensive things
    3. Investing money
    4. Losing money
      1. Poor judgement

A document can contain multiple top-level headings:

<!DOCTYPE HTML>
<title>Alphabetic Fruit</title>
<h1>Apples</h1>
<p>Pomaceous.</p>
<h1>Bananas</h1>
<p>Edible.</p>
<h1>Carambola</h1>
<p>Star.</p>

This would form the following simple outline consisting of three top-level sections:

  1. Apples
  2. Bananas
  3. Carambola

Effectively, the body element is split into three.

Mixing both the h1h6 model and the section/h1 model can lead to some unintuitive results.

Consider for example the following, which is just the previous example but with the contents of the (implied) body wrapped in a section:

<!DOCTYPE HTML>
<title>Alphabetic Fruit</title>
<section>
 <h1>Apples</h1>
 <p>Pomaceous.</p>
 <h1>Bananas</h1>
 <p>Edible.</p>
 <h1>Carambola</h1>
 <p>Star.</p>
</section>

The resulting outline would be:

  1. (untitled page)
    1. Apples
    2. Bananas
    3. Carambola

This result is described as unintuitive because it results in three subsections even though there's only one section element. Effectively, the section is split into three, just like the implied body element in the previous example.

(In this example, "(untitled page)" is the implied heading for the body element, since it has no explicit heading.)

Headings never rise above other sections. Thus, in the following example, the first h1 does not actually describe the page header; it describes the header for the second half of the page:

<!DOCTYPE HTML>
<title>Feathers on The Site of Encyclopedic Knowledge</title>
<section>
 <h1>A plea from our caretakers</h1>
 <p>Please, we beg of you, send help! We're stuck in the server room!</p>
</section>
<h1>Feathers</h1>
<p>Epidermal growths.</p>

The resulting outline would be:

  1. (untitled page)
    1. A plea from our caretakers
  2. Feathers

Thus, when an article element starts with a nav block and only later has its heading, the result is that the nav block is not part of the same section as the rest of the article in the outline. For instance, take this document:

<!DOCTYPE HTML>
<title>We're adopting a child! — Ray's blog</title>
...

<h1>Ray's blog</h1>

<main>
 <article>
<header>
  <nav>
   <a href="?t=-1d">Yesterday</a>;
   <a href="?t=-7d">Last week</a>;
   <a href="?t=-1m">Last month</a>
  </nav> 
</header>
  <h2>We're adopting a child!</h2>

  <p>As of today, Janine and I have signed the papers to become
  the proud parents of baby Diane! We've been looking forward to
  this day for weeks.</p>
</article> 
</main>
...

The resulting outline would be:

  1. Ray's blog
    1. Untitled article
      1. Untitled navigation section
    2. We're adopting a child!

Also worthy of note in this example is that the header and main elements have no effect whatsoever on the document outline.


※ 原文:http://www.w3.org/TR/2014/REC-html5-20141028/sections.html#headings-and-sections