HTML5覚書　〜コンテンツ・カテゴリーにコンテンツ・モデルを添えて〜


普段バックエンドをやっていてフロントエンドが苦手な人間の備忘録（忘備録）です。

## コンテンツ・カテゴリー
[MDN Web Docs - コンテンツカテゴリー](https://developer.mozilla.org/ja/docs/Web/Guide/HTML/Content_categories)
HTML5ではブロック要素とインライン要素による分類が廃止されましたが[^1]、その代わりとなるのがコンテンツ・カテゴリーやコンテンツ・モデルによる分類です。HTML5の要素（タグ）の "ほとんど" は、以下7つのカテゴリーに分類されます。

[^1]: 『ブロック要素とインライン要素による分類が廃止』とは書きましたが、それぞれの要素が持つ表示特性としては、引き続き「ブロック要素」「インライン要素」という分類が可能です。[MDN Web Docs - ブロックレベル要素](https://developer.mozilla.org/ja/docs/Web/HTML/Block-level_elements) / [MDN Web Docs - インライン要素](https://developer.mozilla.org/ja/docs/Web/HTML/Inline_elements)


1. メタデータ・コンテンツ
1. フロー・コンテンツ
1. セクショニング・コンテンツ（区分コンテンツ）
1. ヘディング・コンテンツ（見出しコンテンツ）
1. フレージング・コンテンツ（記述コンテンツ）
1. エンベッディッド・コンテンツ（埋め込みコンテンツ）
1. インタラクティブ・コンテンツ（対話型コンテンツ）

ひとつの要素が複数のカテゴリーを跨いで分類されることもあるため、各カテゴリーの関係性を図にすると以下のようになります。
![category2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/fa3f73bc-43d1-a8f3-08f4-ef5024c6cf72.png "HTMLコンテンツカテゴリー図")
```<html>```、```<li>``` などは、どのカテゴリーにも属さない要素であり、逆に```<a>```、```<span>```などは、複数カテゴリーに属する要素となります。

[MDN Web Docs - ＜html＞: HTML 文書 / ルート要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/html)
[MDN Web Docs - ＜li＞](https://developer.mozilla.org/ja/docs/Web/HTML/Element/li)
[MDN Web Docs - ＜a＞: アンカー要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a)

例として[＜span＞タグのリファレンス](https://developer.mozilla.org/ja/docs/Web/HTML/Element/span)を見てみます。

span要素の**コンテンツ・カテゴリー**は、```フローコンテンツ``` と ```記述コンテンツ（フレージングコンテンツ）``` のふたつに属すると書かれています。
また、**許可されている内容**（子要素）には ```記述コンテンツ``` が、**許可されている親要素**には ```記述コンテンツを受け入れるすべての要素、またはフローコンテンツを受け入れるすべての要素``` との記載があります。
![span2@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/893e0618-0d1d-960f-780d-e15ab5c935cf.png)

次に、各コンテンツ・カテゴリーの概要を見てみましょう。

### 1. メタデータ・コンテンツ
タイトルやメタデータ、表示方法や本文外の情報などを表すコンテンツ。
主に```<head>```要素内で使用することが多い。

**このカテゴリーに属する要素**
```<base>, <link>, <meta>, <noscript>, <script>, <style>, <title>```

### 2. フロー・コンテンツ
テキスト関連や埋め込みコンテンツなど、主に```<body>```内で使用されることの多いコンテンツ。

**このカテゴリーに属する要素**
```<a>, <abbr>, <address>, <article>, <aside>, <audio>, <b>, <bdo>, <bdi>, <blockquote>, <br>, <button>, <canvas>, <cite>, <code>, <data>, <datalist>, <del>, <details>, <dfn>, <div>, <dl>, <em>, <embed>, <fieldset>, <figure>, <footer>, <form>, <h1>, <h2>, <h3>, <h4>, <h5>, <h6>, <header>, <hgroup>, <hr>, <i>, <iframe>, <img>, <input>, <ins>, <kbd>, <label>, <main>, <map>, <mark>, <math>, <menu>, <meter>, <nav>, <noscript>, <object>, <ol>, <output>, <p>, <picture>, <pre>, <progress>, <q>, <ruby>, 
, <samp>, <script>, <section>, <select>, <small>, <span>, <strong>, <sub>, <sup>, <svg>, <table>, <template>, <textarea>, <time>, <ul>, <var>, <video>, <wbr> および文字列。
```
下記の要素は、特定の条件が満たされている場合にのみ、このカテゴリーに属する。

- ```<area>``` : <map> 要素の子孫の場合
- ```<link>``` : itemprop 属性がある場合
- ```<meta>``` : itemprop 属性がある場合
- ```<style>``` : scoped 属性がある場合

### 3. セクショニング・コンテンツ（区分コンテンツ）
文章区分や節など、セクション（区切り）を表すコンテンツ。

**このカテゴリーに属する要素**
```<article>, <aside>, <nav>, <section>```

### 4. ヘディング・コンテンツ（見出しコンテンツ）
見出しを表すコンテンツ。

**このカテゴリーに属する要素**
```<h1>, <h2>, <h3>, <h4>, <h5>, <h6>```

### 5. フレージング・コンテンツ（記述コンテンツ）
文章中で使用するコンテンツ。HTML4やXHTMLの「インライン要素」に近い概念で、これら記述コンテンツが集まることによって段落が構成される。

**このカテゴリーに属する要素**
```<abbr>, <audio>, <b>, <bdo>, <br>, <button>, <canvas>, <cite>, <code>, <data>, <datalist>, <dfn>, <em>, <embed>, <i>, <iframe>, <img>, <input>, <kbd>, <label>, <mark>, <math>, <meter>, <noscript>, <object>, <output>, <picture>, <progress>, <q>, <ruby>, <samp>, <script>, <select>, <small>, <span>, <strong>, <sub>, <sup>, <svg>, <textarea>, <time>, <var>, <video>, <wbr> および通常の文字列（空白文字だけで構成されたものを除く）。```

下記の要素は、特定の条件が満たされたときのみ、このカテゴリーに属する。

- ```<a>``` : 記述コンテンツだけを含む場合
- ```<area>``` : <map> 要素の子孫である場合
- ```<del>``` : 記述コンテンツだけを含む場合
- ```<ins>``` : 記述コンテンツだけを含む場合
- ```<link>``` : itemprop 属性がある場合
- ```<map>``` : 記述コンテンツだけを含む場合
- ```<meta>``` : itemprop 属性がある場合

### 6. エンベッディッド・コンテンツ（埋め込みコンテンツ）
文書に他のリソースを取り込んだり、他のマークアップ言語や名前空間を挿入したりするコンテンツ。主な用途としては、画像、動画、音声などの文書内への埋め込み。

**このカテゴリーに属する要素**
```<audio>, <canvas>, <embed>, <iframe>, <img>, <math>, <object>, <svg>, <video>```

### 7. インタラクティブ・コンテンツ（対話型コンテンツ）
ユーザとやり取りをするためのコンテンツ。リンクやフォームなど、ユーザーが操作することのできるものが基本となる。

**このカテゴリーに属する要素**
```<a>, <button>, <details>, <embed>, <iframe>, <keygen>, <label>, <select>, <textarea>```

下記の要素は、特定の条件下にある場合のみ、このカテゴリーに所属。

- ```<audio>``` : controls 属性がある場合
- ```<img>``` : usemap 属性がある場合
- ```<input>``` : type 属性が hidden 状態ではない場合
- ```<menu>``` : type 属性が toolbar 状態ではない場合
- ```<object>``` : usemap 属性がある場合
- ```<video>``` : controls 属性がある場合

## コンテンツ・モデル
HTML5では「コンテンツ・モデル」という概念もあります。
[HTML Living Standard](https://html.spec.whatwg.org/) の中の [3.2.5 Content models](https://html.spec.whatwg.org/#content-models) に記載がありますが、コンテンツ・モデルとは**要素の予想されるコンテンツの説明** (a description of the element's expected contents) とされていて、要するに「子要素として入れられる内容にはどんなものが許可されるか」を説明するのがコンテンツ・モデルだと考えれば良いかと思います。

例えば[＜p＞タグのリファレンス](https://developer.mozilla.org/ja/docs/Web/HTML/Element/p)を見てみると、「許可されている内容」に「記述コンテンツ」とありますが、これが```<p>```タグの**コンテンツ・モデル**ということになります。
![p2@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/f931a763-16d8-4d92-0d88-1131cc80bf27.png)
```<p>```タグの中に```<span>```タグを入れるような良くある実装も、かつてのHTML4などではブロック要素(p)の中にインライン要素(span)を入れるという説明をしていましたが、HTML5においては、「子要素として許可されているのは記述コンテンツであるため```<p>```タグの中に```<span>```タグ（記述コンテンツ）を入れられる」と説明できるということです。

```html
<p>
    <span>pタグの中には「記述コンテンツ」を入れられる。</span>
</p>
```

### 透過的コンテンツ・モデル
HTML5には**透過的コンテンツ・モデル** ( [transparent content model](https://html.spec.whatwg.org/#transparent-content-models) ) という概念もあります。
該当するのは以下の要素です。

- a 要素
- ins 要素
- del 要素
- object 要素
- video 要素
- audio 要素
- map 要素
- noscript 要素
- slot 要素
- canvas 要素
- 自律的カスタム要素

これらの要素のようにコンテンツ・モデルが「透過」であるとされる場合、各要素の「許可されている内容」（子要素）はあくまで**親要素に準じる**というカタチになります。
踏み込んだ説明をすると**「透過的な要素が削除されたりその子要素で置き換えられたりしても、それ自身のコンテンツが必ず妥当な HTML5 として構造化されているもの」**が透過なコンテンツモデルを持つそうですが、いったんは、子要素として許可されるコンテンツは親要素の性質を受け継いで決められるという点が理解できれば良いかと思います。

今度は HTML Living Standard で[＜a＞タグに関するリファレンス (4.5.1 The a element)](https://html.spec.whatwg.org/#the-a-element) を見てみます。

> **Content model:**
Transparent, but there must be no interactive content descendant, a element descendant, or descendant with the tabindex attribute specified.

とあると思いますが、**Transparent**と書かれている箇所が「透過」という意味になりますので、```<a>```タグはコンテンツ・モデルが透過＝子要素として許可されるコンテンツは親要素次第だということになります。（対話型コンテンツは除く、とも書いてあります。）

例えば下記のようなマークアップは、HTML4などのブロック要素/インライン要素の感覚で言えば間違ったマークアップのように見えるかもしれませんが、HTML5で```<a>```タグのコンテンツモデルは**透過**となるため、```<a>```タグは親要素の```<div>```のコンテンツ・モデルを引き継いで、```<p>```タグ等のフローコンテンツを子要素として持てるようになります。

```html
<div>
  <a>
    <p>a要素は透過的コンテンツ・モデル</p>
  </a>
</div>
```

### その他のコンテンツ・カテゴリーやコンテンツ・モデル
その他にも、二次的なカテゴリーがあるとか、セクショニング・ルート（区分化ルート）、パルパブル・コンテンツ、スクリプト対応要素、知覚可能コンテンツ、フォーム関連コンテンツ...など触れられていない話題もありますが、もっと自身の理解が深まったらまた書くかもしれません。


#### 参考URL
[HTML - Living Standard](https://html.spec.whatwg.org/multipage/dom.html#kinds-of-content)
[＜初心者向け＞知っておきたいHTML5の基本【マークアップ編 その1】](https://www.asobou.co.jp/blog/web/html5-3)
[＜初心者向け＞知っておきたいHTML5の基本【マークアップ編 その2】](https://www.asobou.co.jp/blog/web/html5-4)
[HTML5 に於ける"透過的な内容"。](https://www.marguerite.jp/Nihongo/WWW/RefHTML/HTML5/Content/Transparent.html)
[トランスペアレントについて](https://www.tagindex.com/html5/basic/transparent.html)
[透過的コンテンツモデルの仕様について知りたいです](https://ja.stackoverflow.com/questions/75812/%e9%80%8f%e9%81%8e%e7%9a%84%e3%82%b3%e3%83%b3%e3%83%86%e3%83%b3%e3%83%84%e3%83%a2%e3%83%87%e3%83%ab%e3%81%ae%e4%bb%95%e6%a7%98%e3%81%ab%e3%81%a4%e3%81%84%e3%81%a6%e7%9f%a5%e3%82%8a%e3%81%9f%e3%81%84%e3%81%a7%e3%81%99/75814#75814)