HTML5でのコーディング – セクションやらアウトラインやらのコンテンツ・モデル周辺のお話

ここでは HTML5 で採用されているコンテンツ・モデル周辺のお話をします。具体的にはセクションアウトラインについて、article 要素と section 要素の使い分けについて書いていきます。「HTML5 ではいくつ h1 要素を使っても大丈夫」というのを聞いたことのある人は、これを読むとその理由がわかるかもしれません。

HTML5以前とHTML5でのマークアップにおける考え方の違い

HTML5 以前のときは Web ページを見たときに、この部分がヘッダーでここがフッター、でもってメインイメージがあってレフトコンテンツがあって…みたいにして見た目でパーツに分けていました。そしてそれぞれに対応するように div 要素をつくってマークアップしました。 <div id="header"> だの<div id="left-contents"> とかってヤツです。 "left-contents" (左側のコンテンツ)のような名前をつけるわけですから、HTML のマークアップの時点ですでにレイアウト(見た目)を意識したものになってます。

これが HTML5 では『コンテンツ・モデル』というのになりました。おおざっぱにいうと『レイアウトは全部 CSS にまかせてしまって HTML ファイルでは文書構造を明確にしたマークアップをしなさい』ということです。なので、Web ページを見たときにどの部分がコンテンツとして独立なのかとか、どこからどこまでが意味のあるまとまりなのかとかそんな感じのことを考えながらマークアップします。極端な例えかもしれませんが、HTML5 でのマークアップの仕方を十分習得していると、内容は同じだけどデザインだけが異なる2つの Web ページについてまったく同じマークアップができるはずです。HTML5 でのマークアップは見た目ではなくて内容に関するマークアップですから。

そしてこのとき重要になってくるのが、HTML5 で導入された新要素です。特にセクショニング・コンテンツと呼ばれる articleasidenavsection 要素です。これらに関してはセクションやアウトラインといった概念を説明した後に使い分けを見ていきます。

参考ページ

コンテンツ・モデルによる要素の分類

HTML5 以前と HTML5 では要素の分類が変わりました。これが決定的な違いです。HTML5 以前では要素を『インライン要素』と『ブロックレベル要素』に分類していました。インライン要素というのは、要素を並べるとブラウザ上で改行されずに右に配置されていく要素です。a 要素や span 要素が代表的です。一方のブロックレベル要素というのは並べると改行されて下に向かって表示されるものです。div 要素や p 要素がその代表例です。

Web ページを作成するときにレイアウトの役割を担うのは CSS です。HTML ではありません。でも HTML5 以前では HTML 自体も要素の分類の部分でレイアウトを意識したものになっていました。要素が右に配置されていくか下に配置されていくか、それによって要素を分類していたからです。

HTML5 ではこの分類に変わって『コンテンツ・モデル』が採用されました。コンテンツ・モデルでは HTML の要素は7つのカテゴリ

  • メタデータ・コンテンツ
  • フロー・コンテンツ
  • セクショニング・コンテンツ
  • ヘディング・コンテンツ
  • フレージング・コンテンツ
  • エンベッディット・コンテンツ
  • インタラクティブ・コンテンツ

に分類されます。中には複数のカテゴリに属する要素もあります。これによってHTML5 ではコンテンツというのを主軸においてコーディングしていくことになります。どの要素がどのカテゴリに分類されているかは参考ページを読んでください。

参考ページ

『セクション』、『アウトライン』という概念

7つのカテゴリに属する要素のうち、使い方を必ず理解しておかないといけないものがセクショニング・コンテンツとヘディング・コンテンツです。それぞれ次のような特徴をもっています;

  • セクショニング・コンテンツ

    見出しやフッターの範囲を定義する。潜在的に見出しとアウトラインをもつ。
    articleasidenavsection 要素がこれに属する。

  • ヘディング・コンテンツ

    セクションのヘッダーを定義する。
    h1h2h3h4h5h6 要素がヘディング・コンテンツに属する。

セクショニング・コンテンツがセクションという範囲を定義して、セクションのまとまりがアウトラインになります。

…ただこれだけだとイミフなのでコードを書いてアウトラインを見てみます。まずはこのコード

<body>
  <section>
    <h1>hoge</h1>
    <p>hogehogehoge</p>
  </section>
  <article>
  </article>
</body>

をコピーしてHTML 5 Outlinerの「HTML:」の下に貼付けて「Outline this!」をクリックしてください。すると 

1. Untitled Section
    1. hoge
    2. Untitled Section

というテキストが表示されます。これがアウトラインです。HTML5文書の階層構造のことです。

まずは hoge のところ。ここはセクショニング・コンテンツである section 要素で h1 要素と p 要素を囲っています。h1 要素の内容は "hoge" です。セクショニング・コンテンツは潜在的に見出しをもつ、ということでした。この潜在的な見出しと、ヘディング・コンテンツに属する要素である h1 が結びついて "hoge" がアウトラインに表示されてます。つまり潜在的な見出しがヘディング・コンテンツによって明示的に宣言されている訳です。そして p 要素で定義される段落がそのセクションの内容になります。"hoge" という見出しと "hogehogehoge" という段落(内容)を含むセクションが section 要素の定義するセクションです。

次に 2. Untitled Section のところ。ここはセクショニング・コンテンツである article 要素がつくるセクションです。でも article 要素は h1 などのヘディング・コンテンツを含みません。なので "Untitled Section"、つまり『見出しをもたないセクション』だと認識されたわけです。また article 要素の中には先ほどのような p 要素もありません。ですがたとえ空っぽでもセクショニング・コンテンツはセクションを新たに定義します。

ここまでをまとめるとこんな感じです:

<body>
  <section>
<!-- ここから"hoge"という見出しをもったセクションが開始される -->
    <h1>hoge</h1>
    <p>hogehogehoge</p>
<!-- ここで"hoge"という見出しをもったセクションが終了する -->
  </section>
  <article>
<!-- ここから見出しをもたない名無しのセクションが開始される -->
<!-- ここで見出しをもたない名無しセクションが終了する -->
  </article>
</body>

アウトラインを見ると一番上にも Untitled Section というのがあります。これは何でしょうか。先ほど『セクションのまとまりがアウトライン』といいました。このアウトラインというのは「何の」アウトラインかというと、セクショニング・ルートのアウトラインなんです。セクショニング・ルートになりうる要素は6つありますが、ここでのセクショニング・ルートはズバリ body 要素です。セクショニング・ルート自身はアウトラインの最上位セクションを定義するのでやはり暗黙の見出しをもちます。ですが body 要素の下にはヘディング・コンテンツがありません。なのでアウトラインには "Untitled Section" と表示されたということです。

また section 要素も article 要素も body 要素内にあります。このとき、sectionarticle がつくるセクションは body 要素がつくるセクションの子セクションとなります。「ネストされたセクション」ともいいます。ということでまとめるとこんな感じです:

<body>
<!-- ここから見出しをもたない名無しセクションが開始される -->
  <section>
<!-- ここから"hoge"という見出しをもった子セクションが開始される -->
    <h1>hoge</h1>
    <p>hogehogehoge</p>
<!-- ここで"hoge"という見出しをもったセクションが終了する -->
  </section>
  <article>
<!-- ここから見出しをもたない名無しの子セクションが開始される -->
<!-- ここで見出しをもたない名無しセクションが終了する -->
  </article>
<!-- ここで見出しをもたない名無しセクションが終了する -->
</body>

とりあえず HTML5 では見出しと内容をもったセクションというのが基本単位になって、そのまとまりがHTML文書のアウトラインと呼ばれる階層構造をつくるということを理解してください。繰り返します。基本単位はセクションで、セクションのまとまりがつくる階層構造がアウトラインです。

参考ページ

ヘディング・コンテンツと暗黙のセクション

次にこんなコードのアウトラインを見てみましょう:

<body>
  <h1>hoge</h1>
  <section>
    <h1>foo</h1>
    <p>foofoofoo</p>
  </section>
  <h2>bar</h2>
</body>

アウトラインはこんな感じになります:

1. hoge
    1. foo
    2. bar

んっ?ってなりました?sectionarticleasidenav もないのに "bar" が新たなセクションの見出しとして認識されてます。復習を兼ねて一つずつ見ていきましょう。まずはセクショニング・ルートである body 要素がつくるセクションが始まります。見出しは h1 要素になっている "hoge" です。次いで section 要素が新たなセクションを開始します。そのセクションの見出しは h1 要素になっている "foo" です。このセクションは "hoge" という見出しのセクションの子セクションになります。そして section 要素で作られるセクションが終了した後、 h2 要素になっている "bar" がきます。これが新たなネストされたセクションの見出しになっています。

実はセクション内に2つ以上のヘディング・コンテンツがあると、2つ目以降のヘディング・コンテンツの要素によって暗黙的に新たなセクションが開始されます。そしてその新たなセクションの見出しがそのヘディング・コンテンツになります。今の場合でいうと、body 要素にはすでに h1 要素である "hoge" があるために、下の "bar" という h2 要素によって新たなセクションがつくられ、そのセクションの見出しが "bar" になる、というわけです。

コードで説明するとこんな感じです:

<body>
<!-- ここから"hoge"という見出しをもったセクションが開始される -->
  <h1>hoge</h1>
  <section>
<!-- ここから"foo"という見出しをもった子セクションが開始される -->
    <h1>foo</h1>
    <p>foofoofoo</p>
<!-- ここで"foo"という見出しをもったセクションが終了する -->
  </section>
<!-- ここから"bar"という見出しをもった子セクションが開始される -->
  <h2>bar</h2>
<!-- ここで"bar"という見出しをもったセクションが終了する -->
  </article>
<!-- ここで"hoge"という見出しをもったセクションが終了する -->
</body>

次の例はこれです:

<body>
  <h1>hoge</h1>
  <h2>foo</h2>
  <h3>bar</h3>
</body>

アウトラインはこんな感じになります:

1. hoge
    1. foo
        1. bar

それほど難しくないと思います。セクショニング・ルートである body 要素が "hoge" という見出しのセクションをつくって、h2 要素によって暗黙的にセクションが開始されてその見出しが "foo" になります。そのセクションは body がつくるセクションの子セクションになっています。 h3 要素によってさらに新たなセクションがつくられて、その見出しは "bar" になります。そしてそれは見出しが"foo"のセクションの子セクション、body がつくるセクションの孫セクションとなっています。

最後にもう一つ例を出します:

<body>
  <h1>hoge</h1>
  <section>
    <h2>foo</h2>
    <p>foofoofoo</p>
    <h1>baz</h1>
  </section>
  <h2>bar</h2>
  <h1>quux</h1>
</body>

この場合のアウトラインはこうなります:

1. hoge
    1. foo
    2. baz
    3. bar
2. quux

これはちょっとクセがあります。また順番に見ていきましょう。まずは body によって最上位のセクションが開始されます。見出しは "hoge" です。次いで section 要素によって子セクションが開始されます。見出しは "foo"、段落は "foofoofood" です。ここまでは OK でしょう。

次に h1 要素がきています。もしこれが h3h4h5h6 であれば、"foo" を見出しにもつセクションの子セクションが開始されます。ところが "foo" の見出しレベル h2 に対して "baz" の見出しが h1 なので、暗黙に開始されるセクションは子セクションではなく兄弟セクションになります。セクションの見出しと同じかそれよりも高いレベルの見出しがある場合、section 要素の中に入っているにも関わらず、section 要素がつくるセクションと兄弟関係にある暗黙的セクションが開始される わけです。

section 要素を抜けると、h2 要素によって "bar" という見出しの暗黙セクションが開始されます。これは直前で閉じられている section 要素によってつくられるセクションと兄弟関係にあります。

最後に h1 要素によって "quux" という見出しの暗黙セクションが始まります。これは body 要素の中に入っていますが、body 要素の見出しである "hoge" の見出しレベルと同じ h1 です。ということは先ほど説明したとおり、body要素がつくるセクションと兄弟関係にある暗黙的セクションが暗黙的に開始 されることになります。なので "quux" と "hoge" はアウトライン上では同じ階層のセクションの見出しということになります。

まとめるとこんな感じです;

  • セクショニング・ルートである body 要素は最上位のセクションをつくる
  • セクションの見出しになるのは、そのセクションをつくる要素内にある最初のヘディング・コンテンツの要素である
  • 二つ目以降のヘディング・コンテンツの要素は暗黙のセクションをつくる
  • 暗黙のセクションをつくる要素の見出しレベルが、その要素が含まれるセクションの見出しレベルと同じかそれ以上のとき、要素が含まれているセクションと兄弟関係にあるセクションが暗黙的につくられる

参考ページ

なぜ HTML5 は h1 要素をいくつも使えるのか

ここまでついてこれたあなた、暗黙的セクションというのがすごく面倒だと思いませんか?そうです、面倒です。なので暗黙セクションを出てこなくさせる方法があります。それはセクションの開始と終了をセクショニング・コンテンツで明示的に宣言することです。さっきの例

<body>
  <h1>hoge</h1>
  <section>
    <h2>foo</h2>
    <p>foofoofoo</p>
    <h1>baz</h1>
  </section>
  <h2>bar</h2>
  <h1>quux</h1>
</body>

であれば

<body>
  <h1>hoge</h1>
  <section>
    <h2>foo</h2>
    <p>foofoofoo</p>
  </section>
  <section>
    <h1>baz</h1>
  </section>
  <section>
    <h2>bar</h2>
  </section>
</body>

と書くことです。下の方は

1. hoge
    1. foo
    2. baz
    3. bar

というアウトラインになります。注意する点は最後の "quux" 部分を削除している点です。"quux" は body 要素がつくるセクションと兄弟関係にあるセクションをつくりました。でも body 要素がつくるセクションと兄弟関係にあるセクションを明示的に宣言する方法は(おそらく)ありません。なのですべて明示的なセクションだけにしたいのなら、body がつくる最上位のセクションと兄弟関係にあるようなセクションはつくるべきではありません。

ここですぐ上のコードの h2h1 に変えてみましょう:

<body>
  <h1>hoge</h1>
  <section>
    <h1>foo</h1>
    <p>foofoofoo</p>
  </section>
  <section>
    <h1>baz</h1>
  </section>
  <section>
    <h1>bar</h1>
  </section>
</body>

これは h2h1 に変える前とまったく同じアウトラインになっています。セクショニング・コンテンツの要素を使ってセクション開始の宣言を明示的に行えば、その中のヘディング・コンテンツ要素の見出しレベルが変わっても同じアウトラインをつくるんです。この意味で「HTML5 ではいくつ h1 を使っても大丈夫」なわけです。こう書いた方がコードもずっと分かりやすくなっています。セクショニング・コンテンツで明示的にセクション開始を宣言する限り、その中の見出しは h1 で大丈夫なんです。

HTML5 以前では h1 要素は一つだけ使うことが望ましいとされていましたが、HTML5 だとそれは「body 要素の直下におく h1 要素は一つだけにするのが望ましい」という意味に変わります。先ほどの例を使うと、

<body>
  <h1>hoge</h1>
  <section>
    <h2>foo</h2>
    <p>foofoofoo</p>
    <h1>baz</h1>
  </section>
  <h2>bar</h2>
  <h1>quux</h1>
</body>

での <h1>quux</h1> のようなものは作らない、ということです。<h1>quux</h1> がつくる暗黙的セクションを明示的に宣言する方法がないからです。

article 要素と section 要素の使い分け

最後にセクショニング・コンテンツに属する要素の使い分けを見てみましょう。以下はHTML5.JP – 次世代HTML標準 HTML5情報サイトからの引用です。

  • article 要素 – セクション – HTML要素 – HTML5 タグリファレンス – HTML5.JP

    article 要素は、ドキュメント、ページ、アプリケーション、サイトの中の自己完結した構成を表します。つまり、シンジケーションのように、単独で再配布でき再利用できるものです。これはフォーラムの投稿、雑誌や新聞の記事、ブログのエントリ、ユーザーが投稿したコメント、インタラクティブなウィジットやガジェット、その他、コンテンツの独立した項目が考えられます。

  • aside 要素 – セクション – HTML要素 – HTML5 タグリファレンス – HTML5.JP

    aside 要素は、その前後のコンテンツには関係しているけれども、やや本筋から逸れながらも軽く触れておきたいようなコンテンツから構成されるページのセクションを表し、コンテンツから分離されたものとして見なすことができます。このようなセクションは、印刷では、よく補足記事として表されるものです。
    この要素は、本文抜粋引用リードや補足記事のような印刷効果、広告、nav 要素のグループ化、ページのメイン・コンテンツから分離しても構わないようなコンテンツに使うことができます。

  • nav 要素 – セクション – HTML要素 – HTML5 タグリファレンス – HTML5.JP

    nav 要素は、他のページやそのページ内の部分へリンクするページのセクション、つまりナビゲーション・リンクを伴うセクションを表します。
    注意:ページ上のすべてのリンクのグループが nav 要素の中にある必要はありません。この要素は、主に、主要なナビゲーション・ブロックからなるセクションを対象としています。とりわけ、サービス規約、ホーム、著作権ページといったサイトのさまざまなページへの短いリンク・リストをフッターに入れることが一般的です。このような場合においてはfooter要素だけで十分です。このような場合にもnav要素を使うことができますが、通常は意味がありません。

  • section 要素 – セクション – HTML要素 – HTML5 タグリファレンス – HTML5.JP

    section 要素は、一般的なドキュメント・セクションやアプリケーション・セクションを表します。セクションとは、この文脈においては、コンテンツの主題をグループ化するものです。通常は見出しを伴います。
    セクションの例としては、章や、タブ付きダイアログ・ボックス内の各種ページや、論文の番号付きセクションがあげられるでしょう。ウェブサイトのホームページは、イントロダクション、新着記事、連絡先情報といったセクションに分けられるでしょう。
    注意:section 要素は、汎用的なコンテナ要素ではありません。スタイリング目的やスクリプティングの都合だけで要素が必要になったときは、ウェブ制作者は、代わりに、div 要素を使うことが推奨されます。一般的な規則として、section 要素は、その要素のコンテンツが明示的にドキュメントのアウトラインにリストされる場合にのみ適切だということです。

長々と引用しましたが使い方は簡単です。セクショニング・コンテンツは上の4つしかなくて、article 要素、aside 要素、nav 要素は section 要素よりも目的がはっきりしているので、articleasidenav のどれかにあてはまりそうならそれを、どれにもあてはまらないのなら section 要素を使えばいい んです。「article 要素と section 要素のどちらを使うべきか」みたいなことを書いてるページがありますが、そういう人は上のリンク先を読み直した方がいいです。article の例がちゃんと書いてありますから。

まとめ

HTML5 でのコーディングで大事なのはセクションを意識したコーディングをするということです。出来上がったコードがきちっとした論理構造をもってるか、HTML 5 Outlinerでアウトラインを確認しましょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です