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 で導入された新要素です。特にセクショニング・コンテンツと呼ばれる article
、aside
、nav
、section
要素です。これらに関してはセクションやアウトラインといった概念を説明した後に使い分けを見ていきます。
参考ページ
-
[HTML5] 新要素まとめ【2014/2/14版勧告候補】 – Qiita
新しく導入された要素をズラッと書いてます。すごく分かりやすいです。HTML5 でのコーディングをする人は必ず読んでここに書いてあることを理解できるようにしておきましょう。
コンテンツ・モデルによる要素の分類
HTML5 以前と HTML5 では要素の分類が変わりました。これが決定的な違いです。HTML5 以前では要素を『インライン要素』と『ブロックレベル要素』に分類していました。インライン要素というのは、要素を並べるとブラウザ上で改行されずに右に配置されていく要素です。a
要素や span
要素が代表的です。一方のブロックレベル要素というのは並べると改行されて下に向かって表示されるものです。div
要素や p
要素がその代表例です。
Web ページを作成するときにレイアウトの役割を担うのは CSS です。HTML ではありません。でも HTML5 以前では HTML 自体も要素の分類の部分でレイアウトを意識したものになっていました。要素が右に配置されていくか下に配置されていくか、それによって要素を分類していたからです。
HTML5 ではこの分類に変わって『コンテンツ・モデル』が採用されました。コンテンツ・モデルでは HTML の要素は7つのカテゴリ
- メタデータ・コンテンツ
- フロー・コンテンツ
- セクショニング・コンテンツ
- ヘディング・コンテンツ
- フレージング・コンテンツ
- エンベッディット・コンテンツ
- インタラクティブ・コンテンツ
に分類されます。中には複数のカテゴリに属する要素もあります。これによってHTML5 ではコンテンツというのを主軸においてコーディングしていくことになります。どの要素がどのカテゴリに分類されているかは参考ページを読んでください。
参考ページ
『セクション』、『アウトライン』という概念
7つのカテゴリに属する要素のうち、使い方を必ず理解しておかないといけないものがセクショニング・コンテンツとヘディング・コンテンツです。それぞれ次のような特徴をもっています;
-
セクショニング・コンテンツ
見出しやフッターの範囲を定義する。潜在的に見出しとアウトラインをもつ。
article
、aside
、nav
、section
要素がこれに属する。 -
ヘディング・コンテンツ
セクションのヘッダーを定義する。
h1
、h2
、h3
、h4
、h5
、h6
要素がヘディング・コンテンツに属する。
セクショニング・コンテンツがセクションという範囲を定義して、セクションのまとまりがアウトラインになります。
…ただこれだけだとイミフなのでコードを書いてアウトラインを見てみます。まずはこのコード
<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
要素内にあります。このとき、section
や article
がつくるセクションは body
要素がつくるセクションの子セクションとなります。「ネストされたセクション」ともいいます。ということでまとめるとこんな感じです:
<body>
<!-- ここから見出しをもたない名無しセクションが開始される -->
<section>
<!-- ここから"hoge"という見出しをもった子セクションが開始される -->
<h1>hoge</h1>
<p>hogehogehoge</p>
<!-- ここで"hoge"という見出しをもったセクションが終了する -->
</section>
<article>
<!-- ここから見出しをもたない名無しの子セクションが開始される -->
<!-- ここで見出しをもたない名無しセクションが終了する -->
</article>
<!-- ここで見出しをもたない名無しセクションが終了する -->
</body>
とりあえず HTML5 では見出しと内容をもったセクションというのが基本単位になって、そのまとまりがHTML文書のアウトラインと呼ばれる階層構造をつくるということを理解してください。繰り返します。基本単位はセクションで、セクションのまとまりがつくる階層構造がアウトラインです。
参考ページ
-
htmlファイルを書いたらここでアウトラインを確認しましょう。
- 見出しとセクション – セクション – HTML要素 – HTML5 タグリファレンス – HTML5.JP
ヘディング・コンテンツと暗黙のセクション
次にこんなコードのアウトラインを見てみましょう:
<body>
<h1>hoge</h1>
<section>
<h1>foo</h1>
<p>foofoofoo</p>
</section>
<h2>bar</h2>
</body>
アウトラインはこんな感じになります:
1. hoge
1. foo
2. bar
んっ?ってなりました?section
も article
も aside
も nav
もないのに "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
要素がきています。もしこれが h3
、h4
、h5
、h6
であれば、"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
がつくる最上位のセクションと兄弟関係にあるようなセクションはつくるべきではありません。
ここですぐ上のコードの h2
を h1
に変えてみましょう:
<body>
<h1>hoge</h1>
<section>
<h1>foo</h1>
<p>foofoofoo</p>
</section>
<section>
<h1>baz</h1>
</section>
<section>
<h1>bar</h1>
</section>
</body>
これは h2
を h1
に変える前とまったく同じアウトラインになっています。セクショニング・コンテンツの要素を使ってセクション開始の宣言を明示的に行えば、その中のヘディング・コンテンツ要素の見出しレベルが変わっても同じアウトラインをつくるんです。この意味で「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
要素よりも目的がはっきりしているので、article
、aside
、nav
のどれかにあてはまりそうならそれを、どれにもあてはまらないのなら section
要素を使えばいい んです。「article
要素と section
要素のどちらを使うべきか」みたいなことを書いてるページがありますが、そういう人は上のリンク先を読み直した方がいいです。article
の例がちゃんと書いてありますから。
まとめ
HTML5 でのコーディングで大事なのはセクションを意識したコーディングをするということです。出来上がったコードがきちっとした論理構造をもってるか、HTML 5 Outlinerでアウトラインを確認しましょう。