コンテントモデル

W3C HTML5 仕様の2014 年 10 月 28 日版の勧告 の「3.2.4 コンテントモデル (Content models)」を和訳したものです。

正確性を求める場合は、原文を参照してください。また、もし本サイトのリファレンスが、最新の仕様と異なる部分がありましたら、ご指摘頂けると幸いです。

3.2.4 コンテントモデル

本仕様で定義されている要素はそれぞれ、コンテントモデルを持ちます。それは、要素の期待されるコンテンツを説明するものです。HTML 要素は、その要素のコンテントモデルで説明されている要件に一致するコンテンツを持たなければいけません。要素のコンテンツとは、DOM における子のことです。ただし、template 要素は除きます。この要素の子は、テンプレートコンテンツの中の子となります(この要素が生成されたときに割り当てられた独立 DocumentFragment)。

スペース文字は、要素の間では常に許されます。ユーザーエージェントは、ソースのマークアップの中にある要素の間のこれらの文字を、DOM の中で Text ノードとして表します。空の Text ノードと、これらの連続した文字だけで構成される Text ノードは、要素間ホワイトスペースとして扱われます。

要素間ホワイトスペース、コメント・ノード、プロセッシング・インストラクション・ノードは、要素のコンテンツがその要素のコンテントモデルに一致しているかどうかを確立するときには、無視されなければいけません。そして、ドキュメントと要素のセマンティクスを定義する次のアルゴリズムに従うときにも、無視されなければいけません。

ゆえに、要素 A と要素 B が同じ親ノードを持ち、それらの間に他の要素も Text ノード(要素間ホワイトスペースを除く)もなければ、要素 A は、二つ目の要素 B の前にある、または、後ろにあると言います。同様に、ある要素が、要素間ホワイトスペースとコメント・ノードとプロセッシング・インストラクション・ノード以外のノードを一つも含まないなら、一つのノードが、その要素の唯一の子となります。

ウェブ制作者は、それぞれの要素に定義されているとおりに明示的に許可されている場所、または、他の仕様で明示的に必須とされている場所でない限り、HTML 要素を使ってはいけません。XML 複合ドキュメントでは、要素が関連のコンテキストを提供するものとして定義されているのであれば、これらのコンテキストは他の名前空間の要素の中に入れることができるでしょう。

たとえば、Atom 仕様には content 要素が定義されています。Atom 仕様では、その type 属性の値が xhtml なら、その中に HTML の div 要素をひとつ入れる必要があります。そのため、このことが本仕様で明示的に規定として言及されていませんが、div 要素はそのコンテキストの中に入れても良いことになります。 [ATOM]

さらに、HTML 要素は、孤立ノードになる場合があります(つまり、親ノードがない)。

例えば、td 要素は tr 要素の中でしか使えないことになっていますが、スクリプトで td 要素を生成しグローバル変数に格納したとしても、それは準拠しています。

var data = {
  name: "Banana",
  cell: document.createElement('td'),
};
3.2.4.1 コンテンツの種類

HTML の要素それぞれは、0 個以上のカテゴリーに属することになります。これは、良く似た特徴を持つ要素を分類するものです。本仕様では、おおまかに次のカテゴリーが使われます:

いくつかの要素は、本仕様の他の部分で定義されている別のカテゴリーにも属します。

これらのカテゴリーの関係は次の通りです:

セクショニング・コンテント、ヘッディング・コンテント、フレージング・コンテント、エンベッディッド・コンテント、インタラクティブ・コンテントは、すべてフロー・コンテントに属します。メタデータ・コンテントは、一部がフロー・コンテントに属します。メタデータとインタラクティブ・コンテントは、一部がフレージング・コンテントに属します。エンベッディッド・コンテントはフレージング・コンテントにも属しますが、一部はインタラクティブ・コンテントにも属します。

他のカテゴリーも特定の目的のために使われます。たとえば、フォーム・コントロールは、共通の要件を定義するために、いくつかのカテゴリーを使って特定されます。中には、特異な要件を持ち、どの特定のカテゴリーにも属さない要素もあります。

3.2.4.1.1 メタデータ・コンテント

メタデータ・コンテントとは、後続のコンテンツの表示や動作をセットしたり、自身のドキュメントと他のドキュメントとの関連性をセットしたり、他の "帯域外" の情報を伝達するコンテンツです。

セマンティクスが主にメタデータ関連(たとえば RDF)となる他の名前空間の要素もまたメタデータ・コンテントです。

ゆえに、XML シリアライゼーションでは、このように RDF を使うことができます:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
 <head>
  <title>Hedralのホームページ</title>
  <r:RDF>
   <Person xmlns="http://www.w3.org/2000/10/swap/pim/contact#"
           r:about="http://hedral.example.com/#">
    <fullName>Cat Hedral</fullName>
    <mailbox r:resource="mailto:hedral@damowmow.com"/>
    <personalTitle>Sir</personalTitle>
   </Person>
  </r:RDF>
 </head>
 <body>
  <h1>私のホームページ</h1>
  <p>私は紐で遊ぶのが好きみたい。お姉ちゃんがリスと遊ぶのも楽しいと
  言うので、ときどきお姉ちゃんに付いて行ってリスと遊ぶのよ。</p>
 </body>
</html>

とはいえ、これは HTML シリアライゼーションでは使えません。

3.2.4.1.2 フロー・コンテント

ドキュメントやアプリケーションの本体に使われるほとんどの要素はフロー・コンテントに分類されます。

3.2.4.1.3 セクショニング・コンテント

セクショニング・コンテントは、見出しフッターの範囲を定義するコンテンツです。

セクショニング・コンテント要素はそれぞれ潜在的に見出しとアウトラインを持ちます。詳細は見出しとセクションのセクションをご覧ください。

セクショニング・ルートとなる要素もあります。これはセクショニング・コンテントとは異なりますが、同じくアウトラインを持ちます。

3.2.4.1.4 ヘッディング・コンテント

ヘッディング・コンテントは、セクションのヘッダーを定義します(明示的にセクショニング・コンテント要素を使ってマークアップしようが、ヘッディング・コンテンツ自身の存在によって示そうが、どちらでも構いません。 )。

3.2.4.1.5 フレージング・コンテント

フレージング・コンテントは、ドキュメントのテキストのことです。段落内のレベルでテキストをマークアップする要素も同様です。段落からフレージング・コンテントが続きます。

フレージング・コンテントとして分類される要素のほとんどは、フレージング・コンテントとして分類される要素しか入れることができません。フロー・コンテントを入れることはできません。

テキストとは、コンテンツ・モデルという文脈においては、何もない、または、Text ノードを意味します。テキストはときにそれ自身のコンテンツ・モデルとして使われますが、それはフレージング・コンテントでもあり、要素間ホワイトスペースになることもあります(Text ノードが空の場合か、スペース文字だけを含んでいる場合)。

Text ノードと属性値はユニコード文字から構成されなければいけません。U+0000 文字を含んではいけませんし、恒久未定義ユニコード文字(非文字)を含んではいけませんし、スペース文字を除く制御文字を含んでもいけません。本仕様は、コンテキストごとに、Text ノードの値と属性の値に関して、制約を加えています。

3.2.4.1.6 エンベッディッド・コンテント

エンベッディッド・コンテントは、ドキュメントに他のリソースを組み込むコンテンツ、もしくは、ドキュメントに挿入される他の語彙のコンテンツのことです。

HTML 名前空間ではない名前空間の要素で、かつ、メタデータではないコンテンツを伝達する要素は、本仕様で定義されるコンテンツ・モデルにおいては、エンベッディッド・コンテントです。(例えば、MathML や SVG)

いくつかのエンベッディッド・コンテンツ要素は、フォールバック・コンテントを持つことができます。このコンテンツは、外部リソースを使うことができない場合(例えば、未サポートのフォーマットだった場合など)に利用するためのコンテンツのことです。この要素の定義では、もしあれば、それはどんなフォールバックなのかが提示されます。

3.2.4.1.7 インタラクティブ・コンテント

インタラクティブ・コンテントは、ユーザーとのやりとりに特化したコンテンツのことです。

HTML のある特定の要素はアクティベーション・ビヘイビアを持ちます。それは、ユーザーがそれらをアクティブにすることができることを意味します。これは、アクティベーション・メカニズムに依存する一連のイベントを引き起こします。通常は、後述の通り、最後には click イベントが発生することになります。

ユーザーエージェントは、アクティベーション・ビヘイビアを持つ要素をユーザーが手動で動作できるようにするべきです。例えば、キーボード利用や音声入力やマウス・クリックを通してです。ユーザーがクリック以外の方法でアクティベーション・ビヘイビアが定義されている要素を動作させるとき、そのインタラクション・イベントのデフォルト・アクションは、その要素で疑似クリック・アクティベーション手順を実行することでなければいけません。

要素はそれぞれ、click in progress フラグを持ち、当初は false にセットされます。

ユーザーエージェントが疑似クリック・アクティベーション手順を実行することになった場合、そのユーザーエージェントは次の手順を実行しなければいけません:

  1. 要素の click in progress フラグが true にセットされているなら、これらの手順を中止します。

  2. 要素の click in progress フラグを true にセットします。

  3. 要素でプレ・クリック・アクティベーション手順を実行します。

  4. 要素で click イベントを発出します。もし click() メソッドが呼び出されたことによって疑似クリック・アクティベーション手順の実行アルゴリズムが呼び出されたなら、isTrusted 属性は false に初期化されなければいけません。

  5. click イベントがキャンセルされなければ、その要素でポスト・クリック・アクティベーション手順を実行します。

    そのイベントがキャンセルされたら、ユーザーエージェントは、その要素でアクティベーション・キャンセル手順を実行しなければいけません。

  6. その要素の click in progress フラグを false にセットします。

ポインティング・デバイスがクリックされたら、ユーザーエージェントは次の手順を実行しなければいけません:

  1. 要素の click in progress フラグが true にセットされているなら、これらの手順を中止します。

  2. 要素の click in progress フラグを true にセットします。

  3. e を、存在すれば、ユーザーによって指定された要素の直近のアクティブ化可能要素(後述します)とします。

  4. 要素 e があれば、その上でプレ・クリック・アクティベーション手順を実行します。

  5. 要求された click イベントを送出します。

    要素 e が存在し、その click イベントがキャンセルされなければ、要素 eポスト・クリック・アクティベーション手順を実行します。

    要素 e が存在し、そのイベントがキャンセルされれば、要素 eアクティベーション・キャンセル手順を実行します。

  6. その要素の click in progress フラグを false にセットします。

上記のアルゴリズムは、ウェブ制作者のスクリプトによって発出される任意の疑似イベントに対しては、実行しません。しかし、click() メソッドを使えば、プログラム的に擬似クリック・アクティベーション手順の実行アルゴリズムを作り出すことができます。

クリック・フォーカス・ビヘイビア(たとえば、ユーザーがテキストフィールドクリックしたときに、それにフォーカスを当てる)は、通常は、マウス・ボタンが最初に押されたときに、つまりクリックが完了する前に発生します。従って、ここではそれについては触れません。

直近のアクティブ化可能要素とは、次のアルゴリズムに要素 target を与えて返される要素のことです:

  1. target が定義済みのアクティベーション・ビヘイビアを持つなら、target を返し、これらの手順を終了します。

  2. target が親要素を持つなら、target にその親要素をセットし、手順の最初に戻ります。

  3. そうでなければ、直近のアクティブ化可能要素はありません。

ユーザーエージェントが要素でプレ・クリック・アクティベーション手順を実行することになったら、その要素に定義されたプレ・クリック・アクティベーション手順があれば、それを実行しなければいけません。

ユーザーエージェントが要素でアクティベーション・キャンセル手順を実行することになったら、その要素に定義されたアクティベーション・キャンセル手順があれば、それを実行しなければいけません。

ユーザーエージェントが要素でポスト・クリック・アクティベーション手順を実行することになったら、その要素に定義されたアクティベーション・ビヘイビアがあれば、それを実行しなければいけません。アクティベーション・ビヘイビアは、この時点に至るまでの前述の手順によって発出された click イベントを参照することができます。

3.2.4.1.8 パルパブル・コンテント

一般的なルールとして、コンテント・モデルがフロー・コンテントフレージング・コンテントを許す要素は、パルパブル・コンテントで、かつ、hidden 属性が指定されていないコンテンツの中に子ノードを少なくとも一つは持つべきです。

この要件はそんなに厳しい要件ではありません。要素が合法的に空になるようなケースが多々あるからです。たとえば、スクリプトによって後で埋められる予定のプレースホルダーとして使われる場合や、その要素がテンプレートの一部で、ほとんどのページでは埋められるけれども、一部のページでは関係がない場合です。

適合性チェッカーは、編集の助けとして、ウェブ制作者がこの要件を満たせていない要素を発見するメカニズムを提供することが推奨されます。

次の要素がパルパブル・コンテント:

3.2.4.1.9 スクリプトサポート要素

スクリプトサポート要素とは、それ自身で何も表さない(つまり、レンダリングされない)要素で、スクリプトをサポートするために使われます。たとえば、ユーザーに対して機能性を提供するなどに使われます。

次の要素がスクリプトサポート要素です:

3.2.4.2 トランスペアレント・コンテントモデル

いくつかの要素は、トランスペアレントだと説明されています。このような要素は、そのコンテントモデルの説明欄に "トランスペアレント" と記述されています。トランスペアレント要素のコンテントモデルは、その親要素のコンテントモデルから派生します。つまり、"トランスペアレント" であるコンテントモデルの役割において求められる要素とは、そのトランスペアレント要素の親のコンテントモデルの役割において求められる要素と同じになります。

例えば、ruby 要素の中にある ins 要素に rt 要素を入れることはできません。なぜなら、ruby 要素のコンテントモデルが ins 要素を許すのは、そのコンテントモデルがフレージング・コンテントを許しているからですが、rt 要素はフレージング・コンテントではないからです。

トランスペアレント要素がお互いにネストされているような場合は、この一連の課程が繰り返し適用されなければいけません。

次のマークアップを考えてみましょう:

<p><object><param><ins><map><a href="/">Apples</a></map></ins></object></p>

"Apples" が a 要素の中で許されるかどうかをチェックするために、そのコンテントモデルを調べます。a 要素のコンテントモデルはトランスペアレントです。map もしかり、ins もしかり、ins 要素を持つ object 要素のコンテントモデルの一部もしかりです。object 要素は p 要素の中にありますが、そのコンテントモデルはフレージング・コンテントです。ゆえに、"Apples" は許されます。なぜなら、テキストはフレージングコンテントだからです。

トランスペアレント要素に親がない場合、"トランスペアレント" であるそのコンテントモデルの役割は、どんなフロー・コンテントでも受け入れるものとして扱われることになります。

3.2.4.3 段落

このセクションで定義している段落という用語は、p 要素の定義の範囲を超えた意味で使われます。ここで定義している段落という概念は、ドキュメントを解釈する方法を説明するために使っています。p 要素は段落をマークアップするいくつかの方法の一つに過ぎません。

段落とは、通常、特定の話題を扱う 1 つ以上の文を伴うテキストのブロックを形成するフレージング・コンテントの連なりことで、印刷における段落と同様です。しかし、より一般的なテーマのグルーピングにも使うことができます。例えば、住所、フォームの一部、署名欄、詩の節も段落と言えます。

次の例には 1 つのセクションの中に 2 つの段落があります。見出しもありますが、段落ではないフレージング・コンテントを含んでいます。コメントと要素間ホワイトスペースが段落を形成しない点に注目してください。

<section>
  <h1>段落の例</h1>
  これは、この例の中で <em>最初の</em> 段落です。
  <p>これは2つ目です。</p>
  <!-- これは段落ではありません。 -->
</section>

フロー・コンテントの中にある段落は、問題を複雑にする a, ins, del, map 要素を除外して、そのドキュメントがどう見えるかに応じて定義されます。なぜ除外するのかというと、それらの要素は、ハイブリッドのコンテントモデル持ち、段落の境界をまたぐことができるからです。これについては、以降の最初の 2 つの例で示されている通りです。

一般的に、要素が段落の境界をまたぐのは避けた方が良いでしょう。そのようなマークアップをメンテナンスするのは難しいと言えます。

次の例は、前の例のマークアップを引き続き使ったものですが、いくつかのマークアップの回りに insdel 要素を入れ、テキストの訂正を示しています(とはいえ、この例では、その訂正に意味はありません)。この例が、 insdel 要素があるにも関わらず、前の例と同じ段落を持っている点に注目してください。ins 要素は見出しと最初の段落をまたいでおり、del 要素は 2 つの段落の間の境界をまたいでいます。

<section>
  <ins><h1>段落の例</h1>
  これは、この例の中で <em>最初の</em> 段落</ins> です<del>。
  <p>これは2つ目です。</p></del>
  <!-- これは段落ではありません。 -->
</section>

view を、ドキュメントにある a, ins, del, map 要素すべてを、それらのコンテンツに置き換えた DOM のビューとします。そして、view の中で、他のタイプのコンテンツによって中断されない連続するフレージング・コンテントのそれぞれに対して、フレージング・コンテントと同様にフレージング・コンテント以外のコンテンツを受け入れる要素の中で、first を一連のノードのうちの最初のノードとし、last を一連のノードのうち最後のノードとします。エンベッディッド・コンテントでも要素間ホワイトスペースでもない少なくとも 1つのノードを構成するそのような連なりに対して、first の直前から last の直後までのオリジナルの DOM の中に、ひとつの段落が存在するということになります。(したがって、段落は a, ins, del, map 要素をまたがった範囲になることができます。)

準拠チェッカーは、お互いに重なり合う段落がある場合、ウェブ制作者に警告することができます(これは、object, video, audio, canvas 要素がある場合、そして、svgmath のように、間接的に HTML が追加で組み込むことができる他の名前空間の要素を通すことで、起こりえます)。

段落p 要素によっても明示的に形成されます。

フレージング・コンテンツ以外のコンテンツがなく、もう段落として分離できないとき、p 要素を使ってその個々の段落を囲むことができます。

次の例では、リンクが、最初の段落の半分から、2 つの段落の間にある見出しの全体、そして 2 つ目の段落の半分まで及んでいます。このリンクは、段落と見出しをまたいでいます。

<header>
 ようこそ!
 <a href="about.html">
  このサイトのテーマは...
  <h1>ファルコン!</h1>
  ロッキード・マーティン社の多目的戦闘機です!
 </a>
 このページでは F-16 ファイティング・ファルコンの真相に迫ります。
</header>

別のマークアップ方法もあります。今度は、明示的に段落を示し、ひとつだったリンクを3つに分割します:

<header>
 <p>ようこそ! <a href="about.html">このサイトのテーマは...</a></p>
 <h1><a href="about.html">ファルコン!</a></h1>
 <p><a href="about.html">ロッキード・マーティン社の
 多目的戦闘機です!</a> このページでは F-16 ファイティング・ファルコンの
 真相に迫ります。</p>
</header>

フォールバック・コンテントを定義する特定の要素を使うときは、段落を重ねることが可能です。次のセクションがその例になります:

<section>
 <h1>私の猫ちゃん</h1>
 あなたは、私の猫のシミュレータと遊べます。
 <object data="cats.sim">
  次のリンクのいずれかを使って、猫シミュレータを見てください:
  <ul>
   <li><a href="cats.sim">シミュレータ・ファイルをダウンロード</a>
   <li><a href="http://sims.example.com/watch?v=LYds5xY4INU">オンライン・シミュレータを使う</a>
  </ul>
  もしくは、メルブロム・ブラウザにアップグレードしてください。
 </object>
 私はこれを誇りに思う。
</section>

5つの段落があります:

  1. "あなたは、私の猫のシミュレータと遊べます。object 私はこれを誇りに思う。" と言っている段落。ここでは、objectobject 要素のことです。
  2. "次のリンクのいずれかを使って、猫シミュレータを見てください:" と言っている段落。
  3. シミュレータ・ファイルをダウンロード" と言っている段落。
  4. "オンライン・シミュレータを使う" と言っている段落。
  5. "もしくは、メルブロム・ブラウザにアップグレードしてください。"と言っている段落。

最初の段落に残りの 4 つの段落が重なっています。"cat.sim" というリソースをサポートしたユーザーエージェントであれば、最初の段落だけを表示するでしょう。しかし、フォールバックを表示するユーザーエージェントでは、紛らわしいことに、最初の段落が 2 つ目の段落と同じ段落にあるかのように表示してしまうでしょう。そして、最後の段落が、あたかも最初の段落の 2 つ目の文の手前にあるかのように表示されてしまうでしょう。

明示的な p 要素を使えば、この混乱を避けることができます。たとえば:

<section>
 <h1>私の猫ちゃん</h1>
 <p>あなたは、私の猫のシミュレータと遊べます。</p>
 <object data="cats.sim">
  <p>次のリンクのいずれかを使って、猫シミュレータを見てください:</p>
  <ul>
   <li><a href="cats.sim">シミュレータ・ファイルをダウンロード</a>
   <li><a href="http://sims.example.com/watch?v=LYds5xY4INU">オンライン・シミュレータを使う</a>
  </ul>
  <p>もしくは、メルブロム・ブラウザにアップグレードしてください。</p>
 </object>
 <p>私はこれを誇りに思う。</p>
</section>