HTML の透過的内容モデル2021年12月13日 22時46分

この記事は HTML アドベントカレンダーの 13 日目の分です。


その昔、HTML 4 の時代には以下のようなコードは仕様違反でした。a 要素はインライン要素であり、その内容にブロックレベル要素である h3 要素は取れなかったからです。

<a href="url"><h3>見出し</h3></a>

現在の HTML 標準では、a 要素、ins 要素、del 要素などは内容モデルが透過的 (transparent) であるとされ、上述のコードも仕様に適合しています。

透過的内容モデルの要素は、その子要素から見ると透過的です。言い換えると、透過的内容モデルの要素が取れる内容は、その親要素が取れる内容を引き継ぎます。ある a 要素の親要素が div 要素なら、その a 要素の内容はフローコンテンツ (flow content) となります。親要素が p 要素なら、内容は記述コンテンツ (phrasing content) となります。

しかしながら、透過的内容モデルの要素は、その親要素から見ると透過的ではありません。透過的内容モデルの要素はどこにでも出現できるわけではないということです。a 要素、ins 要素、del 要素はいずれもフローコンテンツおよび記述コンテンツのカテゴリに属しており、フローコンテンツまたは記述コンテンツが出現できる個所にしか出現できません。以下のように表の行を囲んだりはできないのです。

<table>
  <tbody>
    <!-- a 要素の位置が不適切 -->
    <a href="url">
      <tr>
        <td>cell</td>
        <td>cell</td>
      </tr>
    </a>
  </tbody>
</table>

a 要素がフローコンテンツを内容に取りうるといっても、a 要素に対するデフォルトスタイルシートは display: inline のままであることに注意が必要です。ブラウザによっては display: inline な要素の子要素に display: block な要素があり、かつ flexbox や grid が複雑に絡み合ったときに、要素の高さの計算がまれに意図しない結果になるようです。子要素に display: block な要素がくるときは、a 要素自身にも display: block を指定しておいたほうが安全かもしれません。