表のキャプションは <caption><figcaption>

HTML においてまとまりを持った自己完結の図版や文章にキャプションを付ける場合、 <figure> 要素の子要素として <figcaption> 要素を使うことで表現できます。それとは別に表の場合は専用の <caption> 要素が HTML 3.2 やそれ以前から存在します。

両者は似た面も多いものの歴史的経緯もあり、使い方が異なります。

<caption> 要素の歴史

§

HTML で表が定義されたのは1993年の HTML+(W3C)が最初です。この時点ですでに <caption> 要素は存在しましたが、この時の table は現在のものとは大きく異なる仕様で、とくに <tr> 要素はrow separatorであり、まるで <hr> 要素のように行を区切るためのものとして定義されていました。

<table border>
	<caption>キャプション</caption>
	<th>見出しセル</th><th>見出しセル</th>
	<tr>
	<td>データセル</td><td>データセル</td>
	<tr>
	<td>データセル</td><td>データセル</td>
</table>

そもそも HTML+ 自体が特殊な立ち位置で、文書型宣言の直後は <html> ではなく <htmplus forms=off>(W3C)などという使い方が想定されていたくらいですから、歴史を振り返るにしてもこれは別物として考えたいところです。

HTML+ 以外だと、 HTML 2.0(RFC 1866)までは表は存在せず、1996年の RFC 1942 HTML Tables(datatracker.ietf.org) で規定されたサブセットを HTML 3.2 に取り込む形で登場しました。

RFC 1942 の DTD から主要部分を抜粋します。

<!ELEMENT table - - (caption?, (col*|colgroup*), thead?, tfoot?, tbody+)>

<!ELEMENT caption - - (%text;)+>

<!ENTITY % Caption "(top|bottom|left|right)">

<!ATTLIST caption                  -- table caption --
        %attrs;                    -- id, lang, dir and class --
        align   %Caption; #IMPLIED -- relative to table --
        >

一方、 HTML 3.2 の表定義(W3C)<col> 要素や <tbody> 要素のない簡易的なもので、 <caption> 要素に関しても空の値が許可されたのと、 align 属性値が top, bottom のみという点に違いがあります。

<!ELEMENT table - - (caption?, tr+)>

<!ELEMENT CAPTION - - (%text;)* -- table or figure caption -->
<!ATTLIST CAPTION
        align (top|bottom) #IMPLIED
        >

<caption> 要素に関して RFC 1942 と HTML 3.2 のどちらにも共通するのは以下の点です。現代の HTML とは異なる点も多いですね。

  • <caption> の設置は任意
  • 存在するなら <table> 要素の最初の子要素である必要がある(<table> 要素の子要素定義がカンマ区切りになっていることに注目)
  • 縦方向の表示位置(キャプションをテーブルの上と下のどちらに表示するか)は align 属性で指定する
  • キャプションの中はテキストかインライン要素のみが配置できる
  • 開始タグ、終了タグは省略不可

実務上困るのは <p> 要素などのブロック要素を入れられなかったことで、キャプション内で段落を表現したい場合はやむなく <br> 要素で改行するしかありませんでした。

HTML4 では <col><tbody> が復活(?)して RFC 1942 に近い感じになった一方で、 align 属性が非推奨となりました。

<!ELEMENT TABLE - -
     (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>

<!ELEMENT CAPTION  - - (%inline;)*     -- table caption -->

<!ATTLIST CAPTION
  %attrs;                              -- %coreattrs、%i18n、%events --
  >

また DTD からは読み取れませんが、仕様書本文(W3C)では以下のように summary 属性との関連性が書かれていました。

  • 非視覚的ユーザーエージェント(スクリーンリーダーなど)に依存した利用者にとっては、キャプションは表の目的や構造の要約としては不十分なものになりがち
  • そのため <table> 要素の summary 属性を使用してテーブルの目的と構造を要約した追加情報を提供するように注意せよ

当時は Another HTML-lint gateway(openlab.ring.gr.jp) でも HTML 4.01 で summary 属性のない <table> 要素は減点対象(openlab.ring.gr.jp)で、省略しても文法違反でこそないものの基本的には付けるべきという空気感がありましたが[1]、この属性は HTML5 で廃止され、現在では 4.9.1.1 Techniques for describing tables(WHATWG) にあるように <p> 要素、あるいは <figure> 要素などを使い、非視覚環境だけでなくすべてのユーザーに対して説明情報を含めるべきという考え方になっています。

さて、やや脇道に逸れましたが話を <caption> 要素に戻して、 HTML5 では当初コンテンツモデルがフレージングコンテンツでしたが、2009年8月25日のアップデート(W3C)でフローコンテンツとなり、複雑なキャプションを表現することが可能になりました。

また W3C HTML 5.3 では2018年2月6日のアップデート(W3C)にて、終了タグの省略が条件付きで許可されるようになりました。どちらが先か時系列は追っていませんが、最新の WHATWG HTML でも同様に省略可能です。

一方で「<table> 要素の最初の子要素にひとつだけ」という、挿入位置と個数の指定は1996年から現在に至るまで一貫して変わっていません。

<figcaption> 要素

§

<figure> 要素とセットで使用し、キャプションや凡例を表します。 HTML5 で登場したもので、当初は <legend> 要素でしたが、2010年3月4日版(W3C)で専用の <figcaption> 要素に分離する形で現在の定義になりました。

<caption> 要素と異なり、 <figure> 要素の最初だけでなく最後の子要素として配置することも可能です。キャプションをコンテンツの下側に表示する場合、<caption> の場合は CSS の caption-side プロパティ(W3C)を使うのに対し、 <figcaption> は HTML 上の挿入位置を変えることで実現します。

このほか、終了タグの省略が認められていない違いもあります。

表のキャプションはどちらを使えばよいのか

§

どちらも使えます。ただし、表を <figure> 要素内に置く場合は以下の注意点があります。

When a table element is the only content in a figure element other than the figcaption, the caption element should be omitted in favor of the figcaption.

4.9.2 The caption element(WHATWG)

table 要素が figure 要素内の figcaption 以外の唯一の内容である場合、 caption 要素は省略されるべきである — figcaption がそれに代るものになるので。

4.9.2 caption要素(triple-underscore.github.io)

すなわち、次のようなマークアップをしてはいけません[2]

<figure>
	<table>
		<caption>表キャプション</caption>
		<tbody>
			...
		</tbody>
	</table>
</figure>

これは私見になりますが、表のキャプション用途として登場した <caption> 要素は、後発の <figcaption> 要素と比べて歴史的な経緯から使い方に差異はあるものの役割は被っており、仕様上廃止扱い(WHATWG)にはなっていないが、マークアップする側の視点としては <figcaption> 要素に統合した方がすっきりするのではないかという感があります。すなわちプロジェクトルールとして <caption> 要素の使用を禁止できないかと考える次第です。そこで表のキャプションを <figcaption> 要素に置き換えた場合、アクセシビリティ面やブラウザ表示における問題がないか考えてみます。

適用ロールとアクセシブルネーム

§

<caption> 要素、 <figcaption> 要素ともに、現時点では暗黙の ARIA セマンティクスは割り当てられていませんが、 WAI-ARIA 1.2 では caption ロール(W3C)が新設され、両要素ともこれが割り当てられる事になります。

また、 HTML Accessibility API Mappings 1.0 ではいくつかの要素についてアクセシブルネームの計算方法が規定されていますが、 <figure> 要素(W3C)<table> 要素(W3C)を比較すると、要素名以外の違いはない事が分かります。

キャプション内のキーボードフォーカス

§

<caption> 要素におけるキャプションを表の下側に表示する場合は CSS の caption-side プロパティ(W3C)を使います。 <caption> 要素を <table> 要素の末尾に配置する事はできません。これはいくつかのメリット、デメリットがあります。

まずメリットとしては、状況によって表示を変えることが可能という点が挙げられます。例えば高さ方向が広い画面ではキャプションは下側、モバイル端末など小さな画面や印刷時には上側にするといった切り替えができます。

一方で、キャプションの中にアンカーリンクやボタンなどのフォーカス可能要素がある場合に caption-side: bottom を指定すると、見た目上の表示位置と実際のフォーカス順序に差異が生じてしまうため、とくに晴眼者がキーボード操作を行うケースにおいて望ましくない挙動となります。

また、 Firefox では <caption> 要素内のフォーカス可能要素に Tab キーで到達できないバグ(bugzilla.mozilla.org)が大昔からあるようで、長い間対応されていません。リンクやボタンがキーボードのみで操作できない状況はかなり致命的なので「特定のブラウザのバグだから」と無下にする判断もしにくいでしょう。ちなみにこれは <caption> 要素に限らず display: table-caption が適用された場合全般で起こるバグのようです。

CSS によるキャプションと表の幅揃え

§

表キャプションをセンタリングしたい場合、 caption { text-align: center } は意図どおりになりますが、 figcaption { text-align: center } は親要素(<figure> 要素)の幅に対してセンタリングされてしまうので、全幅でない表の場合は表とキャプションの中心位置がずれてしまう結果となります。

サムネイル画像
figcaption { text-align: center } だけだと、表とキャプションの中心位置がずれてしまうオリジナル画像

またセンタリングでなくともキャプションの文言が表の横幅より長い場合、キャプションの幅は表の幅に合わせたいところでしょう。

これを解決する方法として、

figure {
	display: table;
}

figcaption {
	display: table-caption;
}

のように <figure> 要素をテーブルの見た目にするテクニックが昔から知られています。この手法は W3C の Web Style Sheets でも紹介されている(W3C)くらいなので、それなりの知名度と信頼性があるように思われていますが、前述のとおりキーボードフォーカスの問題があるので好ましいものではありません。

現在では <figure> 要素に min-content, max-content, and fit-content()(W3C)を設定することで意図どおりの見た目を再現できる事が多いため、表ではない要素に表関連の display プロパティを設定するのは極力避けた方がよいでしょう。


以上、いくつかの視点から <caption> 要素と <figcaption> 要素を比較してみましたが、支援技術(ロール、アクセシブルネーム)や見た目(CSS)に対しては多くのケースでは大差なしと判断できます。

一方でキーボードフォーカスや Firefox の長期に渡るバグなども含めて総合的に考えると、とくにキャプションにフォーカス可能要素が含まれる場合、 <caption> 要素の使用はユーザーのデメリットになってしまうことが考えられるため、表であっても <figure> 要素と <figcaption> 要素を使うことも一考に値するかと思います。

脚注

  • 1.

    ISO/IEC 15445:2000 のように summary属性が仕様として必須になっているものも存在しました。 ↩ 戻る

  • 2.

    2022年5月現在、 Nu Html Checker では何も警告されませんが、 Issue(GitHub)は立っています。 ↩ 戻る