テーブルの応用

前回はテーブルの基礎的な部分を解説しました。今回は応用です。

caption要素

caption要素

要素の種類

テーブルモデル

フロー・コンテンツ

意味

テーブルの説明。

caption要素はテーブルのタイトルや説明を表す要素で、位置はtableの最初の子要素です。つまりtable要素の中の先頭に書くということです。例えば、次のようになります。


<table>
<caption>メニュー</caption>
<thead>
  <tr><th>メニュー</th><th>値段</th></tr>
</thead>
<tbody>
  <tr><td>醤油ラーメン</td><td>¥700</td></tr>
  <tr><td>味噌ラーメン</td><td>¥750</td></tr>
  <tr><td>塩ラーメン</td><td>¥700</td></tr>
</tbody>
</table>

このようにすることで、このテーブルに「メニュー」というタイトルがつきました。

さて、ここで、上に書いたcaption要素の説明で、「子」にフロー・コンテンツというのがあります。これは、caption要素の子にはフロー・コンテンツが使用できるという意味で書いたのですが、そもそもフロー・コンテンツとは何でしょう。

これは、基本的にほとんどすべての要素と言ってもいいです。つまり、子が「フロー・コンテンツ」となっているのは、「基本的に中に何を書いてもいいよ」ということです。フレージング・コンテンツもこれに含まれますし、ただのテキストでもいいです。今回のcaption要素の例もただのテキストですね。

では逆に、フロー・コンテンツに含まれない要素はどんな要素かというと、title要素など(実は他にもあります)のようにhead要素の中に書く要素がまず挙げられます。これらは文書の中身を構成するものではないので当然ですね。

他に、li要素やtr,tdなど、ある特定の要素の子としてしか用いられないものが挙げられます。liは、ulやolなどリストを作るために必要な要素で、li単体では用いられません。ul,olはフロー・コンテンツに含まれます。trやtdなどテーブル関係の要素も同様です。table要素そのものはフロー・コンテンツです。

ただ、注意しておきたいのは、これは文法的な意味合いが強い制約だということです。

例えば、body要素やarticle要素の子もフロー・コンテンツですが、だからといって次のようにするのはおすすめしません。


<!DOCTYPE html>
<html><head><title>タイトル</title></head>
<body>
  こんにちは。
</body>
</html>

この例ではbody要素の中身は「こんにちは。」だけです。これはどうするのが望ましいかというと、次のようにp要素を用いるのがいいです。


<body>
  <p>こんにちは。</p>
</body>

なぜかというと、前者の場合、ブラウザはなぜそこに「こんにちは。」という文が出てくるのはわかりませんが、後者の場合だと、p要素があることでそこに「こんにちは。」という段落があることが認識できます。

文章は段落で構成されるものですから、これなら自然です。このように文法的には合っていても、意味的にはあまり良くない場合というのがあります。

子が同じ「フロー・コンテンツ」であっても、このようにフレージング・コンテンツではなくもっと大きいレベルの子を並べるべきである場合と、captionのように「フレージング・コンテンツが一般的だが、もっと大きいレベルの要素を入れてもよい」という場合に見分けられるようになるとよいでしょう。

フレージング・コンテンツよりも大きいレベルの要素とは何を言いたいかというと、HTML4時代は「ブロック要素」と言われていたもので、HTML5でこれに該当する用語がないのが不思議ですが、基本的には「フロー・コンテンツのうちフレージング・コンテンツでは無いもの」ということです。

具体的にはp要素やh1~h6要素、ul・ol要素、table要素など(他にもまだたくさんありますが)で、これらは文中に挿入したりして使うものではありませんね。だからフレージング・コンテンツではないというわけです。より実用的な見分け方は、基本的にこれらの要素は画面の端から端までを(そこに何も書かれていなくても)占領するため、前後に改行が入った感じになります。

端から端まで占領するとは、つまりこういうことです。

段落1

段落2

段落3

3つの段落に色を付けてみました。こうすると、文字があるところだけでなく端まで色が付いていることがわかります。ここまでがp要素の範囲なのです。

さて、このcaption要素は、さっきのように基本的にはテキスト(などのフレージング・コンテンツ)で事足りますが、長い説明を入れたいときなどはフロー・コンテンツを入れることも可能だというわけです。つまり、次のような感じです。


<table>
<caption>
  <p>当店のおいしいメニューです。ラーメンとご飯物があります。</p>
  <p>おすすめは味噌ラーメンです。</p>
</caption>
<thead>
  <tr><th>メニュー</th><th>値段</th></tr>
</thead>
<tbody>
  <tr><td>醤油ラーメン</td><td>¥700</td></tr>
  <tr><td>味噌ラーメン</td><td>¥750</td></tr>
  <tr><td>塩ラーメン</td><td>¥700</td></tr>
</tbody>
</table>

この例では2つの段落に分けて説明を記述しています。

セルの結合

それでは次の話題に移ります。ここで活躍するのが、td・th要素にあるrowspan属性・colspan属性です。この属性を使うと、セルの結合をすることができます。

「結合」というより、「セルが伸びる」といったほうが適切かもしれません。colspanは右方向、rowspanは下方向です。どういうことかというのを、次のサンプルで見てみましょう。

123
456
789

<table>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>

1~9のセルがある単純なテーブルです。

ここで、次のようにして、1のセルにcolspan属性を設定してみます。


<td colspan="2">1</td>

このように、colspan,rowspanは数値で指定します。すると、次のようになります。

123
456
789

なんと、1のセルが右に伸びて、横幅がセル2つぶんになりました。

2と3のセルは右に押し出されて、3のセルが飛び出ましたね。

同様に、rowspan属性を設定すると次のようになります。


<td rowspan="2">1</td>
123
456
789

今度は下に伸びて、2行目の4,5,6が右に押し出されました。また、次のように両方指定することも可能です。


<td rowspan="2" colspan="2">1</td>
123
456
789

今まで全部2でしたが、3以上にすると同様にその分だけ伸びます。


<td rowspan="3">1</td>
123
456
789

これの実用的な使い方は、例えば次のような感じです。


<table>
<thead>
  <tr><th>メニュー</th><th>値段</th></tr>
</thead>
<tbody>
  <tr><th colspan="2">ラーメン</th></tr>
  <tr><td>醤油ラーメン</td><td>¥700</td></tr>
  <tr><td>味噌ラーメン</td><td>¥750</td></tr>
  <tr><td>塩ラーメン</td><td>¥700</td></tr>
</tbody>
<tbody>
  <tr><th colspan="2">ご飯物</th></tr>
  <tr><td>ライス(小)</td><td>¥200</td></tr>
  <tr><td>ライス(大)</td><td>¥400</td></tr>
  <tr><td>チャーハン</td><td>¥600</td></tr>
</tbody>
</table>
メニュー値段
ラーメン
醤油ラーメン\700
味噌ラーメン\750
塩ラーメン\700
ご飯物
ライス(小)\200
ライス(大)\400
チャーハン\600

メニューが「ラーメン」「ご飯物」の2つに分かれていて、それぞれに見出しを付けました。

ちなみに、こういう感じにすることも可能です。

メニュー値段
ラーメン醤油ラーメン\700
味噌ラーメン\750
塩ラーメン\700
ご飯物ライス(小)\200
ライス(大)\400
チャーハン\600

なかなか複雑ですが、自分でこのとおりに作れるか試してみましょう。

見出しの構造

ところで、このサンプルを見直してみましょう。

メニュー値段
ラーメン
醤油ラーメン\700
味噌ラーメン\750
塩ラーメン\700
ご飯物
ライス(小)\200
ライス(大)\400
チャーハン\600

このテーブルには、「メニュー」「値段」と「ラーメン」「ご飯物」の計4つの見出しがあります。どれがどれに対応しているのでしょうか。

対応しているというのは、それぞれの見出しがどのセルに対する見出しであるかということです。対応している見出しとセルは、「結びついている」などとも言います。

実は、デフォルトだと、まず、テーブルの先頭の行にある見出しは、そこから下にあるセル全てと結び付けられます。

一番上にある見出しセルは「メニュー」「値段」で、そこから下方向なので、これは問題ないですね。

次に、それ以外の見出しセルは、右方向のセルたちに結び付けられます。これはなぜかというと、次のように見出しが左に来るリストというものがあるからです。

名前体重100m走
Aくん72kg15秒84
Bくん95kg9秒58
Cくん58kg14秒20

ところが今回の場合はどうでしょう。他の見出しといえば「ラーメン」と「ご飯物」ですが、右には何もないので、どのセルとも結びついていないということになってしまいます。これでは見出しの意味がありません。

それでは、どう結びつくのが正しいのでしょうか。せっかくcolspan属性を使って横幅を大きくしたのですから、「ラーメン」の場合はその下の3行全部、「ご飯物」の場合もその下の3行全部と結びつけばいいわけです。

このように、見出しセルの結びつき方を指定するための属性があります。それがscope属性です。

scope属性には次の4つの値があり、そのどれかを指定します。

row
右方向のセルと結びつきます。
col
下方向のセルと結びつきます。
rowgroup
その行グループの残りのセル全てと結びつきます。
colgroup
その列グループの残りのセル全てと結びつきます。

rowとcolはさっき説明したような動作です。colgroupにある「列グループ」はまだ解説していないので後述として「行グループ」というのは前回出てきました。

そう、tbody要素でいくつかの行(tr要素)をグループ化できるのでした。行グループとはこれのことです。

実はこれをするために、前回「ラーメン」と「ご飯物」を作ってtbody要素で分けたのです。今回「ラーメン」と「ご飯物」に適用すべきはこのrowgroupです。そうすることで、同じtbody要素の中のセル全てに対して結びつき、希望の動作となります。

列グループ

行グループの木構造
行グループの木構造
列グループ
列グループ

次に、さっき出てきた「列グループ」を解説します。行グループは、tbody要素などを使ってtr要素をひとまとめにしたものでした。

実は、行グループというのは木構造的な構造です。「セル(td,th)は行(tr)に含まれる。行は行グループ(tbody)に含まれる。」という、親と子の関係(含む・含まれるの関係)で記述することができます。

ところが、ここに列グループを加えるとこうはいきません。

列グループを加えると、同じ行(tr要素)に属する各セル(td要素)が別々の列グループに属するということになります。その上、違う行に属するセルが同じ列グループに属したりします。

こうなってしまうと、木構造では表せません。

そこで、HTMLで列グループを表す際は、列グループを表す要素を使っていちいちtd要素を囲んだりしません。「こういう列グループがありますよ」と書いておくだけにとどめます。

そのために使う要素がcolgroup要素です。colgroup要素がある位置は、前述のcaption要素(あれば)より後で、theadやtbodyなどより前です。次のサンプルを持ってきました。


<table>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>

さっきの1~9のテーブルです。これに、例えば次のようにcolgroup要素を加えます。


<table>
<colgroup span="2">
<colgroup span="1">
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>

すると、次のようになります。列グループごとに色分けしてみました。

123
456
789

このように、colgroupを使えば列ごとに色を分けたりするのが楽になります。今はどこがどう楽なのかはわかりませんが、CSSが分かるようになればこの意味が分かると思います。

ここで、colgroupが空要素であることが分かると思いますが、実はcolgroupは不思議な要素で、span属性があるときだけ空要素ということになっています。

それで、このspan属性とは何かというと、これは列の数を指定します。

いったいどういうことかというと、実はcolgroup1つにつき列グループ1つを表します。これは、左から順に、最初の列グループは2列分、次の列グループは1列分、ということだったのです。

それでは、span属性がない場合はどうなのでしょうか。このとき、colgroup要素は空要素ではなくなり、中に子要素を入れることができます。colgroup要素の子要素になるのがcol要素です。

col要素は常に空要素で、colgroupと同じくspan属性を持ち、意味も同じです。このcol要素の役目は何かというと、実はcol要素は「列」を表します。colgroup要素が「列グループ」なので、「この列グループに含まれる列」を表すということになります。col要素にもspan属性があるので、複数の列をひとまとめにしてcol要素で表せます。

ところが、注意すべき点があります。それは、col要素は列グループを作らないということです。col要素で2つ以上の列をまとめたとしても、それは列グループを作ったということではありません。ただ列をまとめて扱っただけです。あくまで、列グループを作るのはcolgroup要素なのです。


<table>
<colgroup>
  <col span="1">
  <col span="1">
</colgroup>
<colgroup span="1">
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>

最初のcolgroupがさっきと変わりました。span="2"がなくなり、代わりに2つのcol要素があります。このcol要素が表す列の集まりが、このcolgroupが作る列グループということになります。

col要素は2つともspan属性が1です。つまり、一番左から1列、そしてさらにもう1列とった合わせて2列が、このcolgroupの列グループになります。要するに「左から2列」です。

しかし、よく考えると、<colgroup span="2">と変わりません。そう、実は、表される列グループは全く変わらないのです。他に、


<colgroup>
  <col span="2">
</colgroup>

例えばこのようにしても変わりません。それでは、col要素など使わずにspan属性ですませばいいと思われます。実際、HTMLだけをやっている限りはそうなのです。このcol要素を使った方法が役立つのは、CSSでテーブルの色分けをするときなどです。同じ列グループだけど異なる色で塗りたい、とかそういうときに役立ちます。CSSを勉強するときが来たら思い出しましょう。

summary属性

最後にsummary属性を紹介します。これは、実はtable要素の属性です。

どんな属性かというと、テーブルの説明を書く属性です。caption要素とかぶっている気がしますね。

この属性は扱いが微妙で、「テーブルを見る人全てにとって役に立つ説明なら、summary属性ではなくcaption要素などの他の方法で書くべきだ」とされています。

例えば目が不自由な人とか、特定の人にとっては役に立つような情報を入れればいいということになっています。しかし、なかなかそういう機会もなく難しい要素なので、特に意識して使う必要もないといえます。