17. 表について

目次

  1. 表概論
  2. CSS表モデル
    1. 匿名表オブジェクト
  3. 列を操作する
  4. 視覚整形モデルにおける表の扱い
    1. 題名の位置と端揃え
  5. 表の内容をレイアウトする
    1. 表の階層とその透過性
    2. 表の幅を計算する: 'table-layout'
    3. 表の高さを計算する
    4. 列を通して文字の位置を揃える
    5. 行や列を動的に操作する
  6. ボーダー
    1. 分離ボーダーモデル
    2. 結合ボーダーモデル
    3. ボーダーの種類
  7. 表を音声出力する
    1. ヘッダの音声出力を制御する: 'speak-header'

17.1 表概論(Introduction to tables)

はデータ間の相互関係を表現する。 文書作成者は、構造化言語によってそれらデータ間の関係を指定し、CSSによって視覚表現、音声表現の体裁を指定する。

文書作成者は、セルの矩形格子として表の視覚整形を指定する。 行と列は、複数まとめて行グループ・列グループとして扱える。 行、列、行グループ、列グループ、及びセルには、それぞれの周囲にボーダーを描くことができる(CSS2にはボーダーのモデルが2種類ある)。 また、特定セルのデータの水平・垂直位置を操作したり、ある列・行に属する全セルのデータ位置を揃えることができる。

また、ヘッダやデータを読み上げる方法など、表の音声出力も制御できる。 音声出力でセルより先にヘッダを読み上げるために、構造化言語のセルとグループにはラベルを付けることができる。 その結果データが適切な順序で出力され、音声ブラウズしているユーザはヘッダの後でデータを聞くことができる。

以下は[HTML40]による3行3列の簡単な表である:

<TABLE>
<CAPTION>This is a simple 3x3 table</CAPTION>
<TR id="row1">
   <TH>Header 1      <TD>Cell 1        <TD>Cell 2
<TR id="row2">
   <TH>Header 2      <TD>Cell 3        <TD>Cell 4
<TR id="row3">
   <TH>Header 3      <TD>Cell 5        <TD>Cell 6
</TABLE>

このソースは、1つの表(TABLE要素)、3つの行(TR要素)、3つのヘッダセル(TH要素)、及び6つのデータセル(TD要素)を生成する。 また、3つの列が暗に特定されていることに注意せよ。 表には、ヘッダ及びデータセルに必要なだけの列が存在しているのである。

次のCSS規則は、ヘッダセル内のテキストを中央揃えにし、データをボールド体のウェイトで表示する:

TH { text-align: center; font-weight: bold }

次の規則は、ヘッダセルのテキストをベースライン揃えにし、各データセルのテキストを行の真ん中の高さに揃える:

TH { vertical-align: baseline }
TD { vertical-align: middle }

次の規則は、1行目が3px幅の青い実線ボーダーに囲われ、他の行が1px幅の黒い実線ボーダーに囲われる様に指定している:

TABLE   { border-collapse: collapse }
TR#row1 { border-top: 3px solid blue }
TR#row2 { border-top: 1px solid black }
TR#row3 { border-top: 1px solid black }

ここで、セル同士の境界で、列を囲むボーダーが重なってしまうことに注意せよ。 row1とrow2の間にできるボーダーは何色になるのだろうか、そしてボーダーの幅はどうなるのだろうか。 この問題については[ボーダーの競合を解決する]で述べる。

次の規則は表の上部に題名を掲げる指定である:

CAPTION { caption-side: top }

そして最後に、次例は音声出力の際に各行を「ヘッダ、データ、データ」の順に読み上げる指定である:

TH { speak-header: once }

たとえば1行目であれば「ヘッダ1、セル1、セル2」の順に読み上げる。 一方次の規則では:

TH { speak-header: always }

同じものを「ヘッダ1、セル1、ヘッダ1、セル2」の順に読み上げることになる。

以上の例では、CSSが[HTML40]の要素に対してどう作用するかを示した。 [HTML40]では、表に関わる様々な要素(TABLE、CAPTION、THEAD、TBODY、TFOOT、COL、COLGROUP、TH、TD)の意味が適切に定めてあるが、他の構造化言語(たとえばXML応用)には、予め表用の要素が存在しない場合もある。 そこでCSS2では、'display'プロパティを用いて、構造化言語の任意の要素に表の役割を割り当てることができる。 たとえば次例では、FOO要素に(HTMLにおける)TABLE要素の役割を与え、BAR要素にCAPTION要素の役割を与えている:

FOO { display : table }
BAR { display : table-caption }

以下の章では表に関する様々な要素について述べる。 本仕様において「表関連要素」(table element)とは、表構築に関わりのある全要素を指す。 また「表内部要素」("internal" table element)とは、行、列、行グループ、列グループ、及びセルを生成する要素を指す。

17.2 CSS表モデル(The CSS table model)

CSS表モデルは、HTML4.0の表モデルを基にしている。 HTML4.0の表構造はその視覚的レイアウトに準じており、任意の題名と、任意数の行及びセルから成る。 このモデルは、構造化言語が列ではなく行を明示することから「行中心」であると言われる。 1度すべての行が定まった後に列が決まるのである(各行先頭のセルは第1列に属する、各行2番目のセルは第2列に属する、以下同様)。 複数の行や列をまとめて構造の一部とし、このグループ単位でスタイルを反映させることもできる(たとえば連続する複数行の周囲にボーダーを描くなど)。

つまり表モデルは、表、題名、行、行グループ、列、列グループ、セルから成る。

CSS表モデルでは、これらすべての表関連要素に対応する要素が、構造化言語に揃っている必要はない。 XML応用のように表専用の要素が存在しない場合、何らかの要素を表関連要素に割り当てる必要があり、これは'display'プロパティで実現する。 以下に挙げる値を用いると、任意の要素に表関連要素としての役割を与えられる:

table(TABLE)
当該要素をブロックの表要素にし、ブロックの整形コンテキストに属する矩形を作り出す。
inline-table(TABLE)
当該要素をインラインの表要素にし、インラインの整形コンテキストに属する矩形を作り出す。
table-row(TR)
当該要素を表の行要素にする。
table-row-group(TBODY)
当該要素を行グループにする。
table-header-group(THEAD)
'table-row-group'と同じだが、視覚整形の際にはあらゆる他の行より先に、題名より後に表示される。 印刷を行うUAは、表が複数のページに渡る場合、各ぺージの先頭にヘッダ行を繰り返してもよい。
table-footer-group(TFOOT)
'table-row-group'と同じだが、視覚整形の際にはあらゆる他の行より後に、下部題名より先に表示される。 ページ媒体を用いるUAは、表が複数のページに渡る場合、各ぺージの末尾にフッタ行を繰り返してもよい。
table-column(COL)
当該要素を列要素にする。
table-column-group(COLGROUP)
当該要素を列グループにする。
table-cell(TD、TH)
当該要素を表のセルにする。
table-caption(CAPTION)
当該要素を表題にする。

'display'の値が'table-column'もしくは'table-column-group'である要素は表示されない(display: noneとして扱われる)が、対応する列にスタイルを設定するのに役立つ。

附記にある[A HTML4.0におけるスタイルシートの例]では、HTML4.0でのこれらの値の使用法を示してある:

TABLE    { display: table }
TR       { display: table-row }
THEAD    { display: table-header-group }
TBODY    { display: table-row-group }
TFOOT    { display: table-footer-group }
COL      { display: table-column }
COLGROUP { display: table-column-group }
TD, TH   { display: table-cell }
CAPTION  { display: table-caption }

HTML文書の'display'プロパティにこれらの値が指定された場合、UAはそれらを無視してもよい。 何故なら、文書作成者はHTML要素に意図されている動作を変更すべきではないからである。

17.2.1 匿名表オブジェクト(Anonymous table objects)

HTML以外の構造化言語が、CSS表モデルの表関連要素をすべて含むとは限らない。 この場合、表モデルが正しく機能するには、構造化言語が含まない表関連要素も存在するものと仮定する必要がある。 それらの表関連要素は、以下の規則に従って匿名オブジェクト(例:表の視覚レイアウトにおける匿名ブロック)を生成する:

  1. いかなる表要素も、必要なだけの匿名表オブジェクトを自身の周囲に自動生成する。 すなわち、少なくとも表もしくは行内表要素、行要素、セル要素に相当する3階層のオブジェクト構造を作り出す。
  2. あるセル要素(以下T)の親要素(以下P)が行要素ではない場合、行要素に相当するオブジェクトをPとTの間に生成する。 このオブジェクトは、Tの兄弟要素のうちTの前後に連続するすべてのセル要素にまたがる。
  3. ある行要素(以下T)の親要素(以下P)が表要素、行内表要素、行グループ要素のいずれでもない場合、表要素に相当するオブジェクトをPとTの間に生成する。 このオブジェクトは、Tの兄弟要素のうち、Tの前後に連続し、かつ親に表要素を必要とするすべての要素にまたがる。 ここで親に表要素を必要とする要素とは、行要素、行グループ要素、ヘッダグループ要素、フッタグループ要素、列要素、列グループ要素、表題要素である。
  4. 行グループ要素、ヘッダグループ要素、フッタグループ要素など(以下T)の親要素(以下P)が表要素と行内表要素のどちらでもない場合、表要素に相当するオブジェクトをPとTの間に生成する。 このオブジェクトは、Tの兄弟要素のうち、Tの前後に連続し、かつ親として表要素を必要とするすべての要素にまたがる。
  5. 行要素(以下P)の子供要素(以下T)がセル要素ではない場合、セル要素に相当するオブジェクトをPとTの間に生成する。 このオブジェクトは、Tの兄弟要素のうちセル要素ではない全要素にまたがる。

次のXMLにおいては、HBOX要素が表要素に含まれているとみなされる:

<HBOX>
  <VBOX>George</VBOX>
  <VBOX>4287</VBOX>
  <VBOX>1998</VBOX>
</HBOX>

何故ならスタイルシートが以下のようになるからである:

HBOX { display: table-row }
VBOX { display: table-cell }

この例だと、ROW要素内のテキストがセル要素に含まれるものとみなされる。 ただし、視覚整形モデルで説明した通り、これらのテキストが更に匿名インラインボックスにも囲われることに注意すること:

<STACK>
  <ROW>This is the <D>top</D> row.</ROW>
  <ROW>This is the <D>middle</D> row.</ROW>
  <ROW>This is the <D>bottom</D> row.</ROW>
</STACK>

スタイルシートは以下のようになる:

STACK { display: inline-table }
ROW   { display: table-row }
D     { display: inline; font-weight: bolder }

HTMLのUAについては、以上の規則に従って匿名オブジェクトを生成する必要はない。

17.3 列を操作する(Column selectors)

表のセルは、行に属しているという見方と、列に属しているという見方が可能である。 文書のソースにおいては、セルは列ではなく行の子孫要素になっている。 それにも拘わらず、プロパティを設定して列単位で操作可能な部分もある。

以下のプロパティは列要素や列グループ要素にも適用できる:

'border'
表要素の'border-collapse'の値が'collapse'である場合に限って、ボーダーの様々なプロパティが適用される。 この時、列や列グループに設定されたボーダーは競合を解決するアルゴリズムに入力され、すべてのセル枠に適切なスタイルが導かれる。
'background'
背景のプロパティを列単位で設定できるが、効果があるのはセルや行の背景が透明な場合に限られる。 [17.5.1 表の階層とその透過性]を参照のこと。
'width'
列幅の最小値を指定する。
'visibility'
'visibility'の値を'collapse'にすると、その列のセルは表示されず、他の列にまたがるセルもその列の部分だけ切り取られる。 更に、表の幅は無くなった列の分だけ短くなる。 詳細は[17.5.5 行や列を動的に操作する]を参照のこと。 'visibility'にこれ以外の値を指定しても無効である。

列を操作する例を挙げておこう。 最初2つの規則で、HTML4.0のrules属性に「cols」を指定した場合と同じ効果が得られる。 3つ目の規則は、合計を書く列の背景を青にする指定である。 最後2つの規則では、固定レイアウトアルゴリズムを利用して列を固定サイズにしている。

COL   { border-style: none solid }
TABLE { border-style: hidden }
COL.totals { background: blue }
TABLE { table-layout: fixed }
COL.totals { width: 5em }

17.4 視覚整形モデルにおける表の扱い(Tables in the visual formatting model)

視覚整形モデルの言葉を借りれば、表の扱いはブロック要素もしくは置換インライン要素である。 他の要素と同様に表も内容、パディング、ボーダー、マージンを有している。

どちらの扱いを受ける場合でも、表要素は匿名ボックスを生成し、表ボックスそのものと(存在すれば)題名ボックスをそこに収める。 表及び題名のボックスは各々が内容領域と周辺領域を有しており、匿名ボックスは両者が収まる最小の寸法を取る。 また、表と題名の間にあるマージンは相殺される。 表を再配置する場合は、題名が常に表から離れない様に、表ボックスだけではなく匿名ボックスごと移動しなければならない。

題名付きの表: 題名と表の両方にマージンが存在し、通常の場合と同様に相殺が行われている [説明]

題名付きの表:題名と表の間にあるマージンは相殺されている

17.4.1 題名の位置と端揃え(Caption position and alignment)

'caption-side'
Value:  top | bottom | left | right | inherit
Initial:  top
Applies to:  'table-caption' elements
Inherited:  yes
Percentages:  N/A
Media:  visual

このプロパティは、題名ボックスの表ボックスに対する相対位置を指定する。 各値は以下の様な意味を持つ:

top
題名ボックスを表ボックスの上に配置する。
bottom
題名ボックスを表ボックスの下に配置する。
left
題名ボックスを表ボックスの左に配置する。
right
題名ボックスを表ボックスの右に配置する。

表要素の上・下にくる題名は、表要素に先行・後行するブロック要素であるかのように整形される。 しかし、(1) 表要素から題名要素へは継承が行われるし、(2) 表要素直前のコンパクト・ランイン要素について考える場合には、題名要素をブロック要素扱いすべきではない。

表ボックスの上下に位置する題名は、幅の算出に際してもブロック要素扱いを受け、表要素の包含ブロック幅を参照する。

表ボックスの左右に位置する題名については、'width'が'auto'以外の値を取るとそれがそのまま題名の幅となる。 'auto'はUAに妥当な選択をするよう委ねる。 UAは題名を「可能な限り狭い幅」にするのも「1行にすべて収める」のも自由である。 したがって、左右の題名幅は'auto'にしない方が無難である。

題名の内容をボックスの端に揃えるには、'text-align'を用いる。 また、表の左右にある題名の垂直位置を揃える場合は、'vertical-align'を用いる。 ただしこの場合、意味を持つ値は'top'、'middle'、'bottom'のみである。 他の値は'top'として扱われる。

次の例では、題名が表の下に配置されている。 題名は表の包含ブロックと同じ幅を持ち、その内容は左揃えになる。

CAPTION { caption-side: bottom; 
          width: auto;
          text-align: left }

以下は題名を(本文の)左マージンに収める例である。 表そのものは左右のマージンを'auto'とすることで中央揃えになり、表と題名を含むボックス全体は、題名の幅だけ左マージンへ侵入している。

BODY {
    margin-left: 8em
}
TABLE {
    margin-left: auto;
    margin-right: auto
}
CAPTION {
    caption-side: left;
    margin-left: -8em;
    width: 8em;
    text-align: right;
    vertical-align: bottom
}

表の幅が包含ブロックの幅より小さいと仮定すれば、以下の様に整形される:

題名がページの左マージンにはみ出している表をセンタリングしたもの [説明]

'margin-left'が負の値なので題名が左マージンにはみ出している

17.5 表の内容をレイアウトする(Visual layout of table contents)

構造化言語の他の要素と同様に、表内部要素も矩形のボックスを生成する。 ただし、表内部要素には、内容、パディング、ボーダーはあるが、マージンは存在しない。

表内部要素のレイアウトは、行と列の不規則な矩形格子から成る。 各ボックスは、以下の規則に従って整数個のセル格子領域を占める。 ただし、この規則はHTML4.0もしくはそれ以前のHTMLには適用されない。 HTMLでは、行や列のさしわたしに独自の制約がある。

  1. 行ボックスは、1行分のセル格子を占める。 同時に、表の最上部から最下部までの全領域を、ソース文書に出現する順序で、行ボックスが占める。(すなわち表全体は行要素と同数の行格子から成る)
  2. 行グループボックスは、自身が含む行要素と同数の行格子を占める。
  3. 列ボックスは、1列もしくはそれ以上のセル格子を占め、出現する順序で横に並べられる。 1列目のボックスは、表に与えられる'direction'の値によって、右端に現れたり左端に現れたりする。
  4. 列グループボックスは、自身が含む列要素と同数の列格子を占める。
  5. 1つのセルが複数の行や列にまたがってもよい。 (CSS2には、またぐ行数や列数を指定する手段が存在しないが、UAは何か別の方法でその情報を取得してよい。 将来はCSSの構文でこの情報を表現できるようになるだろう) したがって、各セルの矩形ボックスは、1つのセル格子、もしくは複数のセル格子の集合と同じ幅・高さを有する。 矩形の最上部に、当該要素の親要素が指し示す行がくる。 また、各矩形はできるだけ左に寄せる必要があるわけだが、複数のセルが重なってはならず、同じ行のセルは、ソースに出現する順序で左から右に並べなければならない。 (前文の制約は'direction'の値が'ltr'の場合に限る。 値が'rtl'の場合は左右を逆に考えよ)
  6. セルボックスは、自身が所属する表や行グループの最終行を下にはみ出してはならない。 はみ出しそうな場合は、ボックスを縮小してでも収めなければならない。

注。 セル要素を相対配置や絶対配置するのは構わないが、余り奨められたものではない。 位置指定や浮動指定はボックスを通常フローから取り除いてしまうので、表の整列に影響が出てしまうのである。

例を挙げよう。 上半分はHTMLである:

<TABLE>
<TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
<TR><TD colspan="2">5
</TABLE>
<TABLE>
<ROW><CELL>1 <CELL rowspan="2">2 <CELL>3 <CELL>4
<ROW><CELL colspan="2">5
</TABLE>

下半分の表は右下図のように整形される。 しかし、HTML(上半分)での表示に明確な定義は無く、CSSでこの定義を明示することもしない。 したがってUAはどう表示しようとも自由である。 たとえば左下図のようにもなり得る。

セル同士が重なる表と重ならない表 [説明]

左側はHTML4.0で不適切な表構造を表示する1つの可能性、 右側はHTML以外で同じ表構造を表示する唯一の可能性

17.5.1 表の階層とその透過性(Table layers and transparency)

各セルの背景を決定するには、表要素が六つの階層に分かれて積み重なっていると考えるのがよい。 ある階層に属する要素の背景は、上位階層の背景が透明である場合にのみ可視となる。

表階層のスキーマ [説明]

表階層のスキーマ

  1. 最下位の階層は表ボックスのみから成る。 他の層と同様、ここも透明であってよい。
  2. 次の階層は列グループから成る。 列グループは表と同じ高さを有するが、表全体を水平方向に覆う必要はない。
  3. 列グループの次の階層は列ボックスから成る。 列グループの場合と同様に、列も表と同じ高さを有するが、表全体を水平方向に覆う必要はない。
  4. 次の階層は行グループから成る。 行グループは表と同じ幅を有し、同時に表全体を上から下まで完全に覆う。
  5. 次の階層は行から成る。 行も表全体を完全に覆う。
  6. 最上位の階層はセルそのものから成る。 図を見ても判るように、すべての行でセルの数が同じでも、全セルが何らかの内容を有するとは限らない。 空のセルは透明になり、下位層が透けて見える。

次の例では、1行目は4つのセルを含んでいるが、2行目にはセルが存在しない。 したがって2行目では、1行目から突き出ている部分を除いて、表要素の背景が透けることになる。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
  <HEAD>
    <STYLE type="text/css">
      TABLE { background: #ff0; border-collapse: collapse }
      TD    { background: red; border: double black }
    </STYLE>
  </HEAD>
  <BODY>
    <P>
    <TABLE>
      <TR>
        <TD> 1 
        <TD rowspan="2"> 2
        <TD> 3 
        <TD> 4 
      </TR>
      <TR><TD></TD></TR>
    </TABLE> 
  </BODY>
</HTML>

この規則は以下のように整形される:

下の行に3つの空セルが存在する表 [説明]

下の行に3つの空セルを含む表

17.5.2 表の幅を計算する(Table width algorithms: the 'table-layout' property)

CSSでは、表の「最適な」レイアウトを定めることはしない。 何故なら、何を最適とするかは人それぞれ異なる場合が多いからである。 その代わりにCSSでは、表のレイアウトに際してUAが最低守るべき制約について定める。 UAは表のレイアウトにいかなるアルゴリズムを用いようと自由であるし、描画速度を精密さより優先してもよい。 ただし「固定レイアウトアルゴリズム」が選択された場合はこの限りではない。

'table-layout'
Value:  auto | fixed | inherit
Initial:  auto
Applies to:  'table' and 'inline-table' elements
Inherited:  no
Percentages:  N/A
Media:  visual

このプロパティは、表のセル、行、列をレイアウトするのに用いるアルゴリズムを制御する。 各値は以下の様な意味を持つ:

fixed
固定レイアウトアルゴリズムを用いる。
auto
任意の自動レイアウトアルゴリズムを用いる。

以下ではこの両アルゴリズムについて述べる。

固定レイアウト

このアルゴリズムでは、表の水平方向のレイアウトがセルの内容量に依存しない。 その代わり、表全体の幅、列幅、ボーダー、そしてセル間距離の影響を受ける。

表全体の幅は'width'を用いて指定するとよい。 この値が'auto'である場合は('display: table'、'display: inline-table'のどちらであっても)自動レイアウトアルゴリズムを使用する。

固定レイアウトアルゴリズムでは、各列幅を以下の様にして決める:

  1. 'width'の値が'auto'以外である列要素は、指定された値をそのまま列幅として用いる。
  2. 列要素の'width'の値が'auto'である場合、1行目のセル要素の'width'の値に着目し、その値が'auto'以外であれば列幅として用いる。 該当するセル要素が複数列に渡る場合、その値は複数列分の幅を表す。
  3. 以上で幅が決まらない列は、残りの水平幅を公平に等分する(もちろんボーダーとセル間距離を考慮して計算する)。

最終的には、表要素の'width'の値と、列幅(ボーダー、セル間距離込み)の合計のうち、大きい方を表の幅にする。 列幅の合計より表の幅の方が大きい場合、余った幅は各列へと適当に配分すべきである。

この方式だと、UAは1行目を受け取ってすぐに表のレイアウトを始められる。 以降に続く行が列幅に影響しないからである。 セルから内容がはみ出す場合は、'overflow'の値に従って処理する。

自動レイアウト

このアルゴリズムに必要なのは一般にたった2つの工程であり、表の幅は列幅(とボーダー幅)から与えられる。 このアルゴリズムは、本仕様執筆時点での一般的なHTMLUAの処理を反映したものである。 UAは、'table-layout'の値が'auto'であっても、表をレイアウトするのにこのアルゴリズムを実装している必要はない。 他のいかなるアルゴリズムを利用しようと自由である。

このアルゴリズムだと、表の全内容を取り込んだ後でないと最終的なレイアウトを決められないので、場合によっては非効率である。 また、複数の処理工程を必要とすることもある。

列幅は以下の様にして決める:

  1. 各セルの最小内容幅を計算する。 整形後の内容が、複数の行にまたがってもよいが、セルボックスをはみ出さないように決める。 セルの'width'の指定値が最小内容幅より大きければ、その指定値が最小セル幅になる。 指定値が'auto'ならば、最小内容幅がそのまま最小セル幅になる。

    同様に、各セルの最大セル幅も計算する。 こちらは、指定位置のみで改行し、自動改行しない場合の幅を用いる。

  2. 各列について、最大及び最小列幅を決める。 対象の列のみをまたぐセルのうち、最も大きな最小セル幅が、その列の最小列幅になる。 ただし、列の'width'の値が更に大きければその値になる。 同様に、対象の列のみをまたぐセルのうち、最も大きな最大セル幅が、その列の最大列幅になる。 ただし、列の'width'の値が更に大きければその値になる。
  3. 複数の列をまたぐセルについて、そのセルがまたぐ各列の最小幅を大きくし、列幅の合計が少なくともその(複数列にまたがった)セル幅以上になるようにする。 また、最大幅についても同じ処理をする。 可能ならば、またいでいるすべての列幅をできるだけ均等に大きくすること。

これによって各列の最小及び最大幅が与えられる。 列幅は最終的な表全体の幅に対して以下の様に影響する:

  1. 表要素や行内表要素の'width'の指定値が'auto'以外なら、その指定値か、列とボーダーとセル間距離を収めるのに必要な最小幅(以下これをMINと書き表す)のうち、大きい方をその算出値とする。 'width'の指定値がMINよりも大きい場合、余りある幅は各列へと均等に配分すべきである。
  2. 表要素や行内表要素の'width'の指定値が'auto'なら、包含ブロック幅とMINのうち、大きい方をその算出値とする。 ただし、列とボーダーとセル間距離を収めるのに十分な最大幅(以下これをMAXと書き表す)が包含ブロック幅より小さければ、MAXを算出値とする。

列幅のパーセント値は表の幅に対する相対値である。 表要素の'width'の値が'auto'である場合のパーセント値は、列幅についてUAができるだけ満足すべき制約だと考える。 (明らかに、制約への満足は常に可能なわけではない。 たとえば、列幅を'110%'にするという制約は満足不可能である)

注。 このアルゴリズムでは、行(グループ)と列(グループ)の両方が、含んでいるセルの寸法と制限し、制限される関係にある。 すなわち、列幅を設定すると行の高さも間接的な影響を受けるのである。 もちろんその逆も同様である。

17.5.3 表の高さを計算する(Table height algorithms)

表の高さは、表要素や行内表要素の'height'の値から与えられる。 この値が'auto'の場合、各行の高さとボーダー及びセル間距離の合計が表の高さになる。 'auto'以外の値は表の高さを明確に表すので、表の高さが行の高さの合計と異なっていてもよい。 CSS2では、指定された高さと内容量による高さが異なる場合の描画方法を定めない。 特に、内容量による高さが指定された高さを上書きすべきかどうか、指定された高さに合わせて余りある垂直スペースをどう配分すべきか、内容量による高さが指定された高さを上回る場合にUAがスクロールの仕組みを提供すべきか、などは定めない。

注。 将来はこれらについても更に規定していく。

行要素の高さは、その行に含まれるセルをUAが認識してはじめて計算される。 すなわち、行要素の'height'の指定値と、セルを収めるのに必要な最小限の高さ(以下これをMINと書き表す)のうち、大きい方を行の高さとする。 行要素の'height'の指定値が'auto'である場合、MINをその算出値とする。 MINの値はセルボックスの高さと垂直位置に依存している(行ボックスの高さを計算するのに似ている)。 CSS2では、行要素や行グループ要素の'height'にパーセント値が指定された時、何の値を参照するかは定めない。

CSS2では、セル要素の'height'の値と、内容を収めるのに必要な最小限の高さ(以下これをMINと書き表す)のうち、大きい方をセルボックスの高さとする。 セル要素の'height'の指定値が'auto'である場合、MINがその算出値となる。 CSS2では、セル要素の'height'にパーセント値が指定された時、何の値を参照するかは定めない。

CSS2では、複数の行をまたぐセルが行の高さの計算に与える影響を定めない。 ただし、またがれる行の高さの合計は、それらをまたぐセルを含むのに十分でなければならない。

各セル要素の'vertical-align'プロパティは、行に対する垂直位置を決める。 各セルには、ベースライン、上線、中心線、下線が存在し、行についても同じことが言える。 セル要素に対しては、'vertical-align'の各値は以下の様な意味を持つ:

baseline
セルのベースラインを、そのセルがまたいでいる先頭の行のベースラインに揃える。 (セル及び行のベースラインの定義については下の説明を参照せよ)
top
セルボックスの上線を、そのセルがまたいでいる先頭行の上線と揃える。
bottom
セルボックスの下線を、そのセルがまたいでいる最終行の下線と揃える。
middle
セルの中心線を、そのセルがまたいでいる行全体の中心線と揃える。
sub、super、text-top、text-bottom
これらの値はセル要素に対して効果を現さない。 代わりにベースライン揃えになる。

セルのベースラインには、そのセルがまたいでいる最初の行ボックスのベースラインを採用する。 セルがテキストを含まない場合、代わりに含まれるオブジェクトのベースラインを用いる。 セルが何も含まない場合、セルボックスの下辺を用いる。 ベースライン揃えになっているセルのベースラインと、そこからセルの上辺までの最大距離は、行のベースラインを設定する際に用いられる。 以下に例を示そう:

セルを縦に揃える例 [説明]

セル要素に対する'vertical-align'の効果を示す図

セルボックス1と2は両者ともベースライン揃えである。 しかし、1より2の方がベースラインから上線までの距離が大きいので、セル2のベースラインがその行のベースラインになる。 ベースライン揃えのセルを含まない行にはベースラインが存在しない(というか必要ない)ことに注意せよ。

曖昧な状況をなくすため、セルの整列は以下の工程を経るものとする:

  1. まず、ベースライン揃えのセルを配置し、それによって行のベースラインを設定する。 その後で上線揃えのセルを配置する。
  2. この時点で、行の上線と(おそらくは)ベースラインが決まっている。 そして、そこまでに配置されたセルの中で最も下に位置する下線から、行の上線までの距離を、暫定的に行の高さとみなす。 (セルのパディングについては下の説明を参照せよ)
  3. この時点で、現在の行の高さを上回る下線揃えもしくは中心線揃えのセルが残っていれば、行の下線を更に下げることによって、最も高さのあるセルに行の高さを揃える。
  4. 残りのセルを配置する。

セルより行の方が高い場合は、上下の空きにパディングを詰める。

17.5.4 列を通して文字の位置を揃える(Horizontal alignment in a column)

セルボックス内部における内容の水平位置は、'text-align'によって指定する。

同列に属する複数のセルが'text-align'の値に<string>を取る時、それらのセルの内容は指定された文字列の先頭を基準軸として揃えられる。 指定された文字列が軸の左右どちら側に位置するかは、書字方向によって決まる。

この揃え方が役に立つのは、テキストが1行に収まる場合に限られる。 セルの内容が複数行に渡る場合の結果は特に定めない。

'text-align'に指定された文字列がセル要素に含まれていない場合、内容の終端を基準軸にする。

基準軸になる文字列は、各セルで同じになる必要はないことに注意されたい。 (同じ文字列を使うのが普通ではあるが)

CSSでは、基準軸として列ボックスの辺に対するオフセットを指定する手段は提供しない。

以下に例を挙げる:

   TD { text-align: "." }
   TD:before { content: "$" }

このスタイルシートを次の表に適用すると、各セルは小数点揃えになる:

  <TABLE>
  <COL width="40">
  <TR> <TH>Long distance calls
  <TR> <TD> 1.30
  <TR> <TD> 2.50
  <TR> <TD> 10.80
  <TR> <TD> 111.01
  <TR> <TD> 85.
  <TR> <TD> 90
  <TR> <TD> .05
  <TR> <TD> .06
  </TABLE>

この例では、試しに:before疑似要素を利用して数値の前に「$」を挿入してみた。 表は以下の様に表示される:

Long distance calls
              $1.30      
              $2.50
             $10.80
            $111.01
             $85.
             $90
               $.05
               $.06

17.5.5 行や列を動的に操作する(Dynamic row and column effects)

行要素、行グループ要素、列要素、列グループ要素には'visibility'に'collaspe'という値がある。 この値を指定すると、該当する行や列は表示から取り除かれ、空いたスペースは他の内容が利用できるようになる。 ただし、行や列が詰められたとしても、それ以外の点で表のレイアウトが影響を受けることはない。 こうすることによって、変化の可能性を考慮して表の再レイアウトをしなくても、行や列を動的に取り除くことができる。

17.6 ボーダー(Borders)

CSSには、セル要素にボーダーを設定するためのモデルが2種類存在する。 一方は個々のセルの周囲に分離したボーダーを表示するモデル、もう一方は表の端から端まで連続したボーダーを表示するモデルである。 どちらのモデルでもきちんとボーダーの種類を決定できるので、どちらを選択するかは多くの場合好みの問題である。

'border-collapse'
Value:  collapse | separate | inherit
Initial:  collapse
Applies to:  'table' and 'inline-table' elements
Inherited:  yes
Percentages:  N/A
Media:  visual

このプロパティは、表に適用するボーダーのモデルを指定する。 'separate'という値は分離ボーダーモデル、'collapse'という値は結合ボーダーモデルを選択する。

17.6.1 分離ボーダーモデル(The separated borders model)

'border-spacing'
Value:  <length> <length>? | inherit
Initial:  0
Applies to:  'table' and 'inline-table' elements
Inherited:  yes
Percentages:  N/A
Media:  visual

長さの値には、隣接する2つのボーダーを分ける距離を指定する。 長さの値が1つだけ指定された場合、その値は水平・垂直両方向のセル間距離になる。 長さの値が2つ指定された場合、前者の値が水平方向のセル間距離に、後者の値が垂直方向のセル間距離になる。 負の長さは不正である。

このモデルでは、個々のセルが別々にボーダーを有する。 'border-spacing'でセル間距離を指定するわけだが、セル間のスペースには表要素の背景が表示される。 行要素、列要素、行グループ要素、列グループ要素はボーダーを有してはならない。(すなわち、UAはこれらの要素に指定されたボーダーのプロパティを無視しなければならない)

下に示した図は、以下の様なスタイルシートを適用した結果である:

  TABLE      { border: outset 10pt; 
               border-collapse: separate;
               border-spacing: 15pt }
  TD         { border: inset 5pt }
  TD.special { border: inset 10pt }  /* The top-left cell */

ボーダーが分離している表 [説明]

'border-spacing'に長さの値を指定した表、個々のセルだけでなく表自体のボーダーも分離している

空セルのボーダーを制御する(Borders around empty cells: the 'empty-cells' property)

'empty-cells'
Value:  show | hide | inherit
Initial:  show
Applies to:  'table-cell' elements
Inherited:  yes
Percentages:  N/A
Media:  visual

分離ボーダーモデルでは、可視の内容を持たないセルについて、このプロパティでボーダーの表示を制御する。 ここで「可視の内容を持たない」とは、内容が空である場合と、'visibility'の値が'hidden'である場合を考える。 「&nbsp;」であるとか、復帰(\0D)行送り(\0A)水平タブ(\09)スペース(\20)を除く空白類文字は、可視の内容に含まれるとする。

このプロパティが'show'という値を取る場合、ボーダーは空セルの周囲にも(通常のセルと同様に)表示される。

'hide'という値は、空セルの周囲にボーダーを表示しないことを意味する。 更に、同じ行のすべてのセルが'hide'という値を取り、なおかつ可視の内容を含まない場合、行全体が'display: none'であるかのようになる。

次の規則は、全セルの周囲にボーダーを表示させる:

TABLE { empty-cells: show }

17.6.2 結合ボーダーモデル(The collapsing border model)

結合ボーダーモデルでは、セル要素、行要素、行グループ要素、列要素、列グループ要素の全体もしくは一部を囲むボーダーを指定できる。 HTMLのrules属性による指定もこの方法で代替可能である。

ボーダーは、セルの間にあるグリッド線を中央の軸として揃えられる。 UAは、最も細かい単位(画面の画素、プリンタの点)で奇数になる値を等分する時、値を丸めるための一貫した規則を有している必要がある。

下の図は、表の幅、ボーダーの幅、パディングの幅、セルの幅の相互関係を示している。 以下の等式がその関係を表している。 表に含まれるすべての行は、この等式に従わなければならない:

row-width = (0.5 * border-width0) + padding-left1 + width1 + padding-right1 + border-width1 + padding-left2 +...+ padding-rightn + (0.5 * border-widthn)

ここで、nとは行に含まれるセルの数を表す。 また、border-widthiとは、i番目のセルとi+1番目のセルの間にあるボーダーを表す。 もっとも外側のボーダーについては、半分だけが表の幅に含まれることに注意されたい。 ボーダーのもう半分はマージン領域に含まれるのである。

セル幅、ボーダー幅、パディング幅の相互関係を表すスキーマ [説明]

セル幅、ボーダー幅、パディング幅の相互関係を表すスキーマ

このモデルでは、表要素のボーダーの半分だけが、表の幅に含まれることを注意されたい。 また、表要素にはパディングが存在しない。(が、マージンはある)

ボーダーの競合を解決する(Border conflict resolution)

結合ボーダーモデルでは、辺が重複する様々な要素(セル要素、行要素、行グループ要素、列要素、列グループ要素、表要素)にボーダーのプロパティを適用し、全セルの四辺にボーダーを指定してよい。 また個々の指定は、ボーダーの幅、種類、色が異なっていてもよい。 競合解決の規則は、各辺が最も「目を引く」<eye chatching>ボーダーを選択することに主眼を置いた。 ただし、'hidden'を指定すると、いかなる状況においてもボーダーを表示しない。

競合が発生した場合、以下の規則に従ってボーダーを決定する:

  1. いかなる競合においても、'border-style'の値'hidden'は最優先する。 この値が適用された箇所にはボーダーを表示しない。
  2. 'none'という値は最も優先度が低い。 その辺に関わるすべての要素についてボーダーのプロパティが'none'という値を取る場合に限って、ボーダーを表示しない。 (ただし、'none'は'border-style'の初期値であることに注意されたい)
  3. 'hidden'という値が全く指定されず、なおかつ'none'以外の値が少なくとも1つ指定されている場合(要するに上記2項に該当しない場合)、より幅が太いボーダーを優先する。 複数の候補が同じ幅である場合、ボーダーの種類に関する優先順序は以下の通り:
    'double'、'solid'、'dashed'、'dotted'、'ridge'、'outset'、'groove'、'inset'
  4. ボーダーの種類も幅も同じで色だけが異なる場合、セル要素に対する指定が最優先され、以下優先度が高い順に、行要素、行グループ要素、列要素、列グループ要素、表要素となっている。

以下の例ではこの優先規則を実際に適用してみた。 このスタイルシートを:

  TABLE          { border-collapse: collapse;
                   border: 5px solid yellow; }
  *#col1         { border: 3px solid black; }
  TD             { border: 1px solid red; padding: 1em; }
  TD.solid-blue  { border: 5px dashed blue; }
  TD.solid-green { border: 5px solid green; }

次のHTMLに適用すると:

<P>
<TABLE>
<COL id="col1"><COL id="col2"><COL id="col3">
<TR id="row1">
    <TD> 1
    <TD> 2
    <TD> 3
</TR>
<TR id="row2">
    <TD> 4 
    <TD class="solid-blue"> 5
    <TD class="solid-green"> 6
</TR>
<TR id="row3">
    <TD> 7
    <TD> 8
    <TD> 9
</TR>
<TR id="row4">
    <TD> 10
    <TD> 11
    <TD> 12
</TR>
<TR id="row5">
    <TD> 13
    <TD> 14
    <TD> 15
</TR>
</TABLE>

この様になる:

ボーダーが結合している表の例 [説明]

結合ボーダーモデルの例

次は行と行の間に罫線を引く例である。 表要素の上ボーダーを'hidden'に設定したので、1行目の上部のボーダーは表示されない。 この例では、HTML4.0のrules属性を実装している。

TABLE[rules=rows] TR { border-top: solid }
TABLE[rules=rows]    { border-collapse: collapse; 
                       border-top: hidden }

横に罫線を引いてある表 [説明]

行間に罫線を引いた表

この場合、表要素に'hidden'を設定しなくても、1行目だけを別に取り出せば同じ効果を実現できる。 どちらの方法を選ぶかはその人の好み次第である。

TR:first-child { border-top: none }
TR { border-top: solid }

結合ボーダーモデルに関して例をもう1つ挙げておこう:

2本のボーダーを取り払った表 [説明]

内部のボーダーを取り払った表

HTMLは以下の通り:

<TABLE style="border-collapse: collapse; border: solid;">
<TR><TD style="border-right: hidden; border-bottom: hidden">foo</TD>
    <TD style="border: solid">bar</TD></TR>
<TR><TD style="border: none">foo</TD>
    <TD style="border: solid">bar</TD></TR>
</TABLE>

17.6.3 ボーダーの種類(Border styles)

'border-style'の値には、表に適用されると意味が変わってしまうものがある、 以下の値一覧でアスタリスクを付けた値がそれに該当する。

none
ボーダーは無し。
*hidden
基本的には'none'と同じ。 ただし、結合ボーダーモデルでは、該当する辺にボーダーを表示するのを禁止する。 (詳細は[ボーダーの競合を解決する]を参照せよ)
dotted
ボーダーを点線にする。
dashed
ボーダーを破線にする。
solid
ボーダーを連続した実線にする。
double
ボーダーを二重線にする。 2本の実線とその間の空白との合計幅が'border-width'の値と等しくなる。
groove
ボーダーをキャンバスの窪みとして表示する。
ridge
'groove'の逆で、キャンバスの隆起としてボーダーを表示する。
*inset
分離ボーダーモデルの場合、ボックスのボーダーより内側全体がキャンバスの窪みになる様に表示する。 結合ボーダーモデルの場合は、'groove'と同じになる。
*outset
分離ボーダーモデルの場合、'inset'の逆で、ボックスのボーダーより内側全体がキャンバスの隆起になる様に表示する。 結合ボーダーモデルの場合は、'ridge'と同じになる。

17.7 表を音声出力する(Audio rendering of tables)

表を音声で出力する場合、データとヘッダの関係は視覚的な並びとは別の方法で表現する必要がある。 音声ブラウザの中には、ユーザが二次元平面内を探ることにより、位置的に表現されたセル間の関係を確認できるようなものも存在する。 しかしそうでない場合、どの時点でヘッダを出力するのかをスタイルシートで指定する必要がある。

17.7.1 ヘッダの音声出力を制御する(Speaking headers: the 'speak-header' property)

'speak-header'
Value:  once | always | inherit
Initial:  once
Applies to:  elements that have table header information
Inherited:  yes
Percentages:  N/A
Media:  aural

このプロパティは、表のヘッダをデータセルごとに出力するか、ヘッダが直前のデータセルと異なる場合にのみ出力するかを指定する。 各値は以下の様な意味を持つ:

once
当該ヘッダに属する一連のデータセルの前で1度だけ出力する。
always
各データセルごとに出力する。

構造化言語には、ヘッダを指定する別の方法が存在することもある。 たとえば[HTML40]では、ヘッダ情報を指定するために3つの属性(headers属性、scope属性、axis属性)がある。 またHTML仕様には、これらの属性が無い場合にヘッダ情報を確認するためのアルゴリズムも用意してある。

MS Wordで作成した表 [説明]

ヘッダとそれに対応するデータが違う行・列に含まれている表

ここでは、San JoseとSeattleを数日間旅行した際の食費、宿泊費、交通費に関するHTMLの表を例に挙げた。 見た目はそうなっていないが、この表にはn次元のヘッダが存在するものと考えてよいだろう。 すなわち「場所」「日付」「出費の内容」「小計」などである。 軸に沿って意味付けされたセルもあれば、表の中に取り敢えず位置を得ただけのセルもある。 この表のマーク付けは以下の通り:

<TABLE>
<CAPTION>Travel Expense Report</CAPTION>
<TR>
  <TH></TH>
  <TH>Meals</TH>
  <TH>Hotels</TH>
  <TH>Transport</TH>
  <TH>subtotal</TH>
</TR>
<TR>
  <TH id="san-jose" axis="san-jose">San Jose</TH>
</TR>
<TR>
  <TH headers="san-jose">25-Aug-97</TH>
  <TD>37.74</TD>
  <TD>112.00</TD>
  <TD>45.00</TD>
  <TD></TD>
</TR>
<TR>
  <TH headers="san-jose">26-Aug-97</TH>
  <TD>27.28</TD>
  <TD>112.00</TD>
  <TD>45.00</TD>
  <TD></TD>
</TR>
<TR>
  <TH headers="san-jose">subtotal</TH>
  <TD>65.02</TD>
  <TD>224.00</TD>
  <TD>90.00</TD>
  <TD>379.02</TD>
</TR>
<TR>
  <TH id="seattle" axis="seattle">Seattle</TH>
</TR>
<TR>
  <TH headers="seattle">27-Aug-97</TH>
  <TD>96.25</TD>
  <TD>109.00</TD>
  <TD>36.00</TD>
  <TD></TD>
</TR>
<TR>
  <TH headers="seattle">28-Aug-97</TH>
  <TD>35.00</TD>
  <TD>109.00</TD>
  <TD>36.00</TD>
  <TD></TD>
</TR>
<TR>
  <TH headers="seattle">subtotal</TH>
  <TD>131.25</TD>
  <TD>218.00</TD>
  <TD>72.00</TD>
  <TD>421.25</TD>
</TR>
<TR>
  <TH>Totals</TH>
  <TD>196.27</TD>
  <TD>442.00</TD>
  <TD>162.00</TD>
  <TD>800.27</TD>
</TR>
</TABLE>

こうしてデータモデルを提供してやれば、音声出力ブラウザは表を様々な角度から分析することができる。 たとえば、各データセルごとに適用される全ヘッダを繰り返して、リストとして出力するのも可能である:

  San Jose, 25-Aug-97, Meals:  37.74
  San Jose, 25-Aug-97, Hotels:  112.00
  San Jose, 25-Aug-97, Transport:  45.00
 ...

あるいは、ヘッダが変わった時にだけ出力することもできる:

San Jose, 25-Aug-97, Meals: 37.74
    Hotels: 112.00
    Transport: 45.00
  26-Aug-97, Meals: 27.28
    Hotels: 112.00
...


Last modified January 24, 1999.
Translated by Kazuteru OKAHASHI.
mailto:okahashi@nets.ne.jp