🐈‍⬛

コンテンツカテゴリの所属って全暗記しないとダメなの?いいえ、そんなことはありません。

に公開

はじめに

日々 HTML と戦っているみなさん、こんにちは。
突然ですが、みなさんは実装中に「この要素に、あの要素を子要素で入れていいんだろうか?」と悩むことはありませんか?
困ったときのエンジニアの味方、 MDN にその答えを求めることは多いと思います。そしてこう思うのではないでしょうか。「これ全暗記しないといかんのか」「いっそ div の悪魔と契約してしまおうか」と……。
この記事では、そんなエンジニアの皆様の葛藤が少しでも減るような、「ざっくりとコンテンツカテゴリを扱うコツ」をお伝えしようと思います。

そもそもコンテンツカテゴリってなに?

もう知ってるよ、という方は読み飛ばしてください。

MDN のコンテンツカテゴリのページを見てみましょう。
https://developer.mozilla.org/ja/docs/Web/HTML/Guides/Content_categories

雑に要約すると、

  • 役割に応じた特徴の分類のこと
  • 子要素として入れることができるカテゴリを定義するのに使われる
  • ほとんどの要素は、 1 つ以上のコンテンツカテゴリに属している(以上、であることがポイント)

です。
試しに、 MDN で span の技術的概要を見てみましょう。
https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/span#技術的概要

  • span はフローコンテンツ、記述コンテンツに属している
  • 子要素に許可されているのは記述コンテンツに属する要素のみ
  • 親要素は記述コンテンツ、フローコンテンツを受け入れる全ての要素

ですね。
span の技術的概要

いやそもそもフローコンテンツとか記述コンテンツって何よ、という話です。
先ほど、コンテンツカテゴリとは「役割に応じた特徴の分類」であると説明しました。では各々のカテゴリってどんな感じよというのを、頻出するものだけ、これまた雑に要約してみます。

カテゴリ名 超要約 要素例
フローコンテンツ body の中に入れられるほとんどの要素、雑に言えばほぼここに属している div , p など
記述コンテンツ 文章内の構成、一部分のマークアップに使用される span , s など
対話型コンテンツ ユーザとのやりとり(操作)が発生するもの button , a など

となります。

まとめると、 span 要素は

  • bodypdiv などの中に入れることができて、
  • 子要素で span をネストしたり、 s で取り消し要素を入れることなどができたりする

要素ということになりますね。

コンテンツカテゴリを「感覚的に理解」する

私はこの記事で、「全部覚えないといけないの?」という全エンジニアの慟哭に、「そんなことはない」とお伝えしたいです。(もちろん、迷うことがあれば MDN 等で確認した方がよいですが)
では、どうすれば感覚的にコンテンツカテゴリまわりを理解できるようになるのでしょうか。

例) button 要素の場合

button 要素を例に挙げてみます。
button 要素は、子孫にも親にも button 要素や a(href 属性を伴う場合) 要素を持つことができません。
https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/button

そういう決まりだから、というと話は早いのですが、それだと決まりを全て覚えないといけませんね。
そこで、このような HTML のイメージをしてみましょう。

<body>
  <button type="button" onclick="action()">
    アクション
  </button>
</body>

ユーザは button くんに対して話しかけました。 button くんは、ユーザに対して応答を返します。

ユーザと button とのやりとり

しかし、このケースではどうでしょう。

<body>
  <button type="button" onclick="action()">
    アクション
    <a href="hoge">
      遷移
    </a>  
  </button>
</body>

ユーザが button くんに話しかけてみました。すると、中にいた a くんが話に割って入ってきてしまいました。

割って入ってきた anchor

ユーザは button くんと話がしたいのに、 a 邪魔すんなや!となりますね。
対話型カテゴリの要素に対話型カテゴリを含んではならない理由です。

例) p 要素の場合

別の例を見てみましょう。
p 要素には、 p 要素を含めることができません。 p 要素は、段落(意味的なまとまり)を表す HTML 要素ですね。
https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/p

仮に、 pp を含んだ場合のマークアップは、このようになります。

<body>
  <p>
    ゲームの話をしましょう。ちなみに、
    <span class="color_red">
      私はヒカセンです。
    </span>
    <p>
      最近読んで面白かった本の話を始めます。
    </p>
  </p>
</body>

新規で作られてしまった意味のまとまり

p ちゃんはゲームのまとまりで話をしようとしているのに、別の p くんが勝手に新しいまとまりで話を始めてしまいました。こちらも先ほどの button の件と同様に、邪魔すんなや!となりますね。
ちなみに、 span 要素は span だけに、特定の範囲(スパン)を示すために用いられる要素ですから、 p の中にいても問題ないという扱いです。

「感覚的理解」のコツ

このように、「要素の振る舞いや役割が分かっていれば、なんとなく中に何を入れたらいけないのか見えてくる」と思います。
そのため、 HTML 要素の意味の知識は最低限必要となってしまいますが、

  • 要素が持つ意味を意識して、マークアップを文章やシチュエーションに置き換える
  • 別の要素を子に取ったとき、子が持つ意味と矛盾が生じないかを考える

これこそが、コンテンツカテゴリをざっくり扱うコツです。

コンテンツカテゴリを意識すると何が良いのか

仕様だから従う!以上!ではあまりに味気ないですね。
もう少し踏み込むと、コンテンツカテゴリを上手に理解して扱うということは、「意味論が通った文章構造を維持している」ことと同義です。
「対話型に対話型をネストすると、対話に割り込みされてしまう」
「段落に段落をネストすると、段落内で別の話が始まってしまう」
これは文章構造としても、意味としても破綻していると言えます。

また、不適切なコンテンツ同士を組み合わせたとしても、令和の超優秀ブラウザくんがよしなに扱ってくれるケースもあります。( p の中に p を入れると勝手に外に出してくれるなど)
しかし、この挙動は各ブラウザに委ねられてしまうところであり、場合によっては実装者が予期していないバグを引き起こすこともあります。

つまりは、コンテンツカテゴリを意識するということは適切なマークアップの実践であり、堅牢な実装を達成していると言い換えることができます。
それに伴って、昨今話題のアクセシビリティの向上も、自然と実現することができるのです。

まとめ

HTML は文章構造である、という大前提に基けば、コンテンツカテゴリを全暗記せずとも適切な使い方に近づけることができます。
HTML を書くとき、いつもよりほんの少し要素の意味や文章構造の流れを意識することで、コンテンツカテゴリに即したマークアップで実装することができるでしょう。

今までコンテンツカテゴリに触れてこなかった方は、ぜひこの記事を参考に、「対話型の中に対話型は NG ですね。なぜなら〜」などレビューコメントを入れてドヤってみては如何でしょうか。

株式会社ZOZO

Discussion