HTML5のコンテンツ・モデルの概念を理解する


# コンテンツ・モデル知ってますか？
以前までヘッダーだろうとフッターだろうと、とにかく目に見える全てをdivで囲っていた私です。今年の４月にようやくHTML5にまともに入門し、さすがにもうHTML5に死角はないな（使いこなせているとは言ってない）と思い始めた今日この頃。つい最近、HTML5に**コンテンツ・モデル**という未知の概念が存在するということを知りました。
はい。そんなわけで。今回は自分自身の知識の定着も含め今回はこのコンテンツ・モデルについて勉強会を開催してみようと思います。

**Make IT アドベントカレンダー23日目**の投稿です。本日は @yu310fu が担当します！
明日は @haduki1208 さんが担当してくださいます。いよいよアドベンドカレンダーも終わりに近づいてきました。

# はじめに
**コンテンツ・モデル**とはHTML5よりブロックレベル要素、インラインレベル要素が廃止され新たに導入された定義のことを指します。
この時点で私は先ず**ブロック、インラインレベル要素の概念がなくなっていたこと**に驚いたのですが、私の浅学さ加減についてはさておきまして、先ずは以下のマークアップソースをご覧ください。

## 誤ったマークアップ例
```html
<span>
    <p>
        <div>誤ったマークアップ例</div>
    </p>
</span>
```
なんか気持ち悪くないですか？
私はこの漠然とした気持ち悪さをブロックレベル要素をインラインレベル要素で囲んだことによるものと思っていましたが、どうやらこの概念は既に**廃止**されていたようです。

上記のソースを正しくマークアップすると以下のようになります。

## 正しいマークアップ例
```html
<div>
    <p>
        <span>正しいマークアップ例</span>
    </p>
</div>
```
これで気持ち悪さがなくなりました。
そもそもなぜ気持ち悪さがを覚えるのか、という話をすると、少し話が長くなりますので次項でお話ししていきたいと思います。

# コンテンツ・モデルの概念を理解する前に
HTML5においてブロックレベル要素・インラインレベル要素は廃止されましたが、新たに導入されたコンテンツ・モデルも基本的にこれらの概念を踏襲したものとなっています。
コンテンツ・モデルではブロックレベル要素・インラインレベル要素がより細分化されており、頭から全てを理解するには個人的に少し煩雑に感じたためブロック・インラインの定義の部分からお話させていただくことにしました。

## ブロックレベル要素とインラインレベル要素
<img width="452" alt="イラスト2.png" src="https://qiita-image-store.s3.amazonaws.com/0/310111/c38b9ce8-beb8-7206-8219-d5eefe7520b4.png">
（引用：[Google Fonts](https://fonts.google.com/)）
ブロックレベル要素は基本的に横幅いっぱいに広がります。ブロックレベル要素はデフォルトでは横に並ばず、flex要素で囲むなどの処理が必要です。文書のかたまり（block）を明示するためのものとお考えください。
インラインレベル要素はブロック要素のように前後の強制改行はいりません。文章の中の一部（inline）装飾するための要素ものとお考えください。

以上の二点を踏まえた上で先ほどの誤ったマークアップ例を見直してみると

```html
<span>
    <p>
        <div>誤ったマークアップ例</div>
    </p>
</span>
```

気持ち悪さの正体がうっすら目に見える気がしませんか？
しかし、冒頭で言った通りこのブロックレベル・インラインレベルの概念は現在は**廃止**されています。
が、初心者が感覚を掴むのにはこちらのほうが個人的にはわかりやすいなと思いました。というのも、コンテンツのレベルが細分化されたことにより、概念自体が非常に煩雑になってしまったからです。

# コンテンツ・モデルの概念を理解する
![イラスト3.png](https://qiita-image-store.s3.amazonaws.com/0/310111/44d33e5f-6f75-8029-cb2d-43c02d383e79.png)
**コンテンツ・モデル**とは、ブロックレベル要素・インラインレベル要素が廃止され新たに導入された定義であり、それぞれの要素にどんな要素を入れることができるかを明示的に示した**配置ルール**のことです。
例えば、ひとつの要素には、**「自身の分類（カテゴリー）」「自身が入れる場所（コンテキスト）」「中に入れていい要素（コンテンツ・モデル）」**の3つが定義されており、これらの分類はおよそ7つに分けられます。

## HTML5における要素の分類はおよそ7つ
| 分類名 | 役割 |
|:-------------------:|:-------------------:|
| メタデータ・コンテンツ（Metadata）  | 文書情報や他の文書との関係を定義するもの  |
| フロー・コンテンツ（Flow） |  子孫にテキストなどを持つもの |
| セクショニング・コンテンツ（Sectioning） | 見出しと概要を付けられるもの |
| ヘッディング・コンテンツ（Heading） | セクションの見出しとなるもの |
| フレージング・コンテンツ（Phrasing）  | 段落などの中に含まれる文節・語句など |
| エンベッディッド・コンテンツ（Embedded） | 文書に他のリソースを埋め込むもの |
| インタラクティブ・コンテンツ（Interactive） | ユーザーによる操作に対応するもの |
（参照：[HTML5リファレンス](http://www.htmq.com/html5/007.shtml "HTML5における要素の分類（コンテンツ・モデル）")）
ややこしいですね。そしてこれが7つに分類されるだけでなく、ひとつの要素が属する分類がひとつだけとは限らないから更にややこしい。
調べてみてわかったのですが、上記の7つの他に**パルパブル・コンテンツ（Palpable）**というものも存在するそうです。話があまりにややこしくなるため今回は深く触れませんが、分類名を直訳すると「明瞭なコンテンツ」という意味になり、これにはaやbuttonなどが含まれるそうです。

## コンテンツ・モデルに基づく正しい記述法
divはFlowのカテゴリに属し、spanはFlow／Phrasing（＋Palpable）のカテゴリに属し、pはFlowのカテゴリに属しています。（参照：[HTML5リファレンス](http://www.htmq.com/html5/007.shtml "HTML5における要素の分類（コンテンツ・モデル）")）
これらのカテゴリ、コンテキスト、コンテンツ・モデルの分類は以下の通りです。

| 要素名 | カテゴリ | コンテキスト | コンテンツ・モデル |
|:--------:|:--------:|:--------:|:--------:|
| div | Flow | Flowが期待される場所 | Flow |
| span | Flow／Phrasing（＋Palpable） | Phrasingが期待される場所 | Phrasing |
| p | Flow | Flowが期待される場所 | Phrasing |

つまり

```html
<span> <!-- Flow／Phrasing （Phrasingしか入れたくない） -->
    <p> <!-- Flow （Phrasingしか入れたくない） -->
        <div>誤ったマークアップ例</div> <!-- Flow （Flowしか入れたくない） -->
    </p>
</span>
```

```html
<div> <!-- Flow （Flowしか入れたくない） -->
    <p> <!-- Flow （Phrasingしか入れたくない） -->
        <span>正しいマークアップ例</span> <!-- Flow／Phrasing （Phrasingしか入れたくない） -->
    </p>
</div>
```
こうすることでそれぞれの要素の分類がかみ合い、構文的にも正しい記述となります。

そして今回はご紹介しませんでしたが、コンテンツ・モデルには上記の表の7つ以外に**Transparent**というものがあります。Transparentは親要素の属性を引き継ぐという特性を持っており、aなどがこれに該当するようです。

これら各要素のコンテンツ・モデルは[W3C HTML5仕様書](https://www.w3.org/TR/html5/)などで調べることができますが、HTML5はそもそもの要素数が膨大なため、それらをひとつひとつを頭に叩き込むのはかなり無理があります。
しかし、冒頭でお話ししている通りこれらの配置ルールは、ブロックレベル要素・インラインレベル要素を踏襲したものになっているように感じました。

もちろんHTML5特有の細かな構文規則はきちんと把握しておく必要がありますが、`HTML5以前のルールに則した（ブロックレベル・インラインレベルで考える）マークアップ`であっても**構文的に大変なことになることはない**と思います。ソースは私です。


# おつかれさまでした
そもそもHTMLは構文的におかしい部分があっても大体が問題なく表示されます。
SEOを気にしないのであれば全てdivで囲んだどころで何も問題はないと思うのですが、可読性や保守性を考えるとやはりマークアップをきちんとこだわることが後々の幸せに繋がりますので日頃からきれいに書く習慣をつけましょうね（戒め）
それでは、長々とお付き合いいただきありがとうございました。おつかれさまでした。

# 参考にしたもの
[HTML5リファレンス](http://www.htmq.com/html5/007.shtml "HTML5における要素の分類（コンテンツ・モデル）")
[コンテンツ・モデルのおはなし](https://speakerdeck.com/atsuco/kontentumoderufalseohanasi "コンテンツ・モデルのおはなし")
[ほんっとにはじめての HTML5 と CSS3](http://honttoni.blog74.fc2.com/blog-entry-107.html "「コンテンツ・モデル」で要素のルールを見てみよう")