Warning:
This wiki has been archived and is now read-only.

CSS2/tables

From HTML5 Chinese Interest Group Wiki
Jump to: navigation, search

表格

内容概要

表格介紹

本章節描述 CSS 裡表格的處理模型,其中的一部分是布局。本章節引入了兩個布局演算法 ― 第一個是固定表格布局演算法,具有完整定義,但是第二個的自動表格布局演算法在本規範中沒有完整定義。

有些廣泛使用的自動表格布局演算法的實作已經有相當接近的兼容性。

表格布局可以用來表示資料之間的列表關係。網頁作者在文件語言描述這些關係之後,可以用 CSS 2.1 指定資料的表現。

在視覺媒介中,CSS 表格可以用來產生某些布局,在這種情況下,網頁作者不該使用文件語言的表格相關元素,而應該在相關的結構元素上使用 CSS 來達到期望的布局。

網頁作者可把表格視為長方形網格來指定視覺排版。表格的行與列可以構成行群組與列群組。網頁作者可在行、列、行群組、列群組、表格單元的周圍設定邊框(CSS2.1 有兩種邊框模型)。網頁作者也可也可以讓一個表格單元中的內容垂直或水平對齊,或是對齊一行或是一列裡的所有表格單元。

這是用 HTML4 描述的一個三行三列的表格:
<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>

這個代碼產生了一個表格(TABLE 元素)、三行(TR 元素)、三個標題單元(TH 元素)與六個資料單元(TD 元素)。請注意例子中的三個列是間接指定的 ― 表格中的列的數目由標題與資料單元決定。

以下 CSS 規則將標題單元裡的文字置中對齊並以粗體呈現:

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

下一個規則將標題單元中的文字與基線對齊並將各個資料單元裡的文字垂直置中:

th { vertical-align: baseline }
td { vertical-align: middle }

下幾個規則將第一個行的周圍設定 3px 的實心藍邊框,在其他行的周圍設定 1px 的實心黑邊框:

table   { border-collapse: collapse }
tr#row1 { border: 3px solid blue }
tr#row2 { border: 1px solid black }
tr#row3 { border: 1px solid black }

然而,行的邊框在行與行接觸的地方有重疊。第一行與第二行中間的邊框的顏色(黑或藍)及粗細(1px 或 3px)是什麼呢?我們在解決邊框衝突小節討論這個問題。

以下規則將表格說鳴放在表格之上:

caption { caption-side: top }

前面的例子說明了怎麼在 HTML 4 元素上使用 CSS 的方法 ― 在 HTML 4 中,各種表格元素(TABLE、CAPTION、THEAD、TBODY、TFOOT、COL、COLGROUP、TH 與 TD)的語意具有完整定義。在其他文件語言(像是 XML 應用程式)不一定有預定義的表格元素,因此, CSS 2.1 讓網頁作者可以用 'display' 屬性將文件語言的元素「對應」到表格元素。舉例來說,以下規則讓 FOO、BAR 元素的行為分別與 HTML TABLE、CAPTION 元素一樣:

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

我們在下一個小節討論各種表格元素。在本規範中,表格元素代表任何參與表格創建的元素,內部表格元素是產生行、行群組、列、列群組或是表格單元的元素。

CSS 表格模型

CSS表格模型基于HTML4表格模型,其中一个表格的结构紧密的构成该表格的可视化布局。在此模型中,一个表格由可选的标题以及任意数目的成行的单元格组成。由于编码人员在文档语言中明确的指定行(而不是列),所以表格模型被认为是“行优先”的。在所有的行都被指定完成之后才会产生列——每一行的第一个单元格属于第一列,第二个属于第二列,以此类推。行和列都可能会在结构上进行分组,这些组会反映在变现上(例如,可能会在行群组周围绘制边框)。

因此,表格模型由表格、标题、行、行群组(包括头部群组和脚部群组)、列、列群组以及单元格组成。

CSS模型不需要包括对应这些部件的元素在内的文档语言。对于没有预定义表格元素的文档语言(例如XML应用),编码人员必须映射文档语言元素到表格元素;这将需要‘display’属性。下列‘display’的值可以将表格格式化规则指派到任意元素上:

table (In HTML: TABLE)

指定一个元素定义一个块级表格:其是一个块格式化上下文中的矩形块。

inline-table (In HTML: TABLE)

指定一个元素定义一个行内表格:其是一个行内格式化上下文中的矩形块。

table-row (In HTML: TR)

指定一个元素为一个单元格组成的行。

table-row-group (In HTML: TBODY)

指定一个元素为至少一个行组成的群组。

table-header-group (In HTML: THEAD)

与‘table-row-group’类似,但对于视觉格式化,此行群组总是显示在所有其他行和行群组之前,且在任意顶部标题之后。印刷用户代理可能会在贯穿表格的所有页面上重复头部行。如果表格包含多个‘display: table-header-group’的元素,则仅有第一个被显示为头部;其他元素被认为与‘display: table-row-group’相同。

table-footer-group (In HTML: TFOOT)

与‘table-row-group’类似,但对于视觉格式化,此行群组总是显示在所有其他行和行群组之后,且在任意底部标题之前。印刷用户代理可能会在贯穿表格的所有页面上重复脚部行。如果表格包含多个‘display: table-footer-group’的元素,则仅有第一个被显示为脚部;其他元素被认为与‘display: table-row-group’相同。

table-column (In HTML: COL)

指定一个元素描述单元格的一列。

table-column-group (In HTML: COLGROUP)

指定一个元素为至少一个列组成的群组。

table-cell (In HTML: TD, TH)

指定一个元素表示一个表格单元格。

table-caption (In HTML: CAPTION)

指定一个表格的标题。所有拥有‘display: table-caption’的元素都必须按照17.4节中的描述显示。

拥有这些‘display’值的替换元素被认为是在布局时给出显示类型。举例说明,一个设置了‘display: table-cell’的图片将会填充空闲单元格控件,并且其大小可能会像普通单元格一样供表格大小算法使用。

‘display’设置为‘table-column’或‘table-column-group’的元素不会显示(正如其拥有‘display: none’),但它们是有用的,因为它们可能会拥有会影响它们所表示的列的某些样式的属性。

附录中的HTML4的默认样式表阐述了HTML4中这些值的意义:

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’属性值,因为HTML表格可能会为了向后兼容使用其他算法显示。但是,这不意味着阻止在HTML的其他、非表格元素上使用‘display: table’。

無名表格物件

非 HTML 的文件語言可不含有 CSS2.1 表格模型的所有元素。在這種情況下,使用者代理必須假設「失蹤」的元素存在以讓表格模型正常運作。所有表格元素皆會在自身周圍生成必要的無名物件,使得原來的元素與無名物件至少構成三層:'table'/'inline-table' 元素、'table-row' 元素與 'table-cell' 元素。消失的元素依照下列規則生成無名物件(例如,視覺表格布局用的無名盒):

在這些規則中,我們使用下述詞彙:

行群組盒

一個 'table-row-group'、'table-header-group' 或 'table-footer-group'

真表格子盒

一個 'table-row' 盒、行群組盒、'table-column' 盒、'table-column-group' 盒或 'table-caption' 盒

真表格行父盒

一個 'table'、'inline-table' 或行群組盒

內部表格盒

一個 'table-cell' 盒、'table-row' 盒、行群組盒、'table-column' 盒或 'table-column-group' 盒

格容器

一個 'table-row' 盒或真表格行父盒

連續

若兩個兄弟盒的中間沒有僅含有空白的無名行內盒以外的兄弟,則稱這兩個兄弟為連續的。若一個兄弟盒序列裡的每一個盒都跟序列裡前面的盒連續,則稱這個兄弟盒序列為連續的。

在這些規則中,流外元素被視為是零寬度零高度的行內元素。這些元素也用同樣規則決定包含塊。

以下的步驟以三個階段進行。

  1. 移除不相關的盒子
    1. 使用者代理必須將 'table-column' 的所有子盒視為具有 'display: none'。
    2. 若一個 'table-column-group' 的子盒 C 不是一個 'table-column',則使用者代理必須將 C 視為具有 'display: none'。
    3. 若盒子 D 是 A 的子嗣而中間不會產生 'table' 或 'inline-table' 盒,則稱 D 為 A 的真表格子嗣。若格容器 P 的子盒 C 是一個僅含有空白的無名行內盒,且 C 前面與後面的兄弟(若存在)是 P 的真表格子嗣且他們是 'table-caption' 盒或內部表格盒,則使用者代理必須將 C 視為具有 'display: none'。
    4. 若盒子 B 是一個僅含有空白的無名行內盒,且 B 在兩個是內部表格盒或 'table-caption' 盒的兄弟之間,則使用者代理必須將 B 視為具有 'display: none'。
  2. 生成失蹤的子包裝:
    1. 若 'table' 或 'inline-table' 的子盒 C 不是一個真表格子盒,則生成一個無名 'table-row' 盒以包圍 C 與不是真表格子盒的連續兄弟。
    2. 若行群組盒的子盒 C 不是一個真表格子盒,則生成一個無名 'table-row' 盒以包圍 C 與不是 'table-row' 盒的連續兄弟。
    3. 若 'table-row' 盒的子盒 C 不是一個 'table-cell' 盒,則生成一個無名 'table-cell' 盒以包圍 C 與不是 'table-cell' 盒的連續兄弟。
  3. 生成失蹤的父盒:
    1. 對於由內部表格盒與 'table-caption' 盒組成的連續兄弟序列裡面的每一個 'table-cell' 盒 C,若 C 的父盒不是 'table-row',生成一個無名 'table-row' 盒以包圍 C 與是 'table-cell' 盒的連續兄弟。
    2. 對於由真表格子盒組成的連續兄弟序列裡面的每一個真表格子盒 C,若 C 的父親不對則生成一個無名 'table' 或 'inline-table' 盒 T 以包圍 C 與是真表格子盒的連續兄弟。(若 C 的父盒是 'inline' 盒,則 T 必須 'inline-table' 盒,否則 C 必須是 'table' 盒。)
      • 若一個 'table-row' 盒的父盒不是行群組盒或 'table'/'lnline-table' 盒,則該盒的父親不對。
      • 若一個 'table-column' 盒的父盒不是 'table-column-group' 盒或 'table'/'lnline-table' 盒,則該盒的父親不對。
      • 若一個行群組盒、'table-column-group' 盒或 'table-caption' 盒的父盒不是 'table' 盒或 'inline-table' 盒,則該盒的父親不對。
在此XML实例中,由于样式表如下:

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

所以假定‘table’元素包含HBOX元素:

<HBOX>
  <VBOX>George</VBOX>
  <VBOX>4287</VBOX>
  <VBOX>1998</VBOX>
</HBOX>
在下面的例子中,假定三个‘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 }

表格单元格可能会从属于两个上下文:行和列。但是,在源文档中,单元格是行的(而不是列的)后裔。然而,另一方面,单元格会都到设置来列上的属性的影响。

下列属性被应用于列以及列群组元素上:

‘border’

只有在表格元素上将‘border-collapse’设为‘collapse’时,才能在列上应用各种边框属性。在这种情况下,设置在列和列群组上的边框将被输入到用于为每个单元格边缘选择边框的冲突解决算法之中。

‘background’

背景属性设置在列中的单元格的背景,但仅在单元格和行的背景为透明时起作用。参见“表格布局及透明。”

‘width’

‘width’属性给出列的最小宽度。

‘visibility’

如果列的‘visibility’被设为‘collapse’,则列中的单元格均不会显示,且会剪裁跨越其他列的单元格。另外,表格的宽度会减去这些列的宽度。参见下面的“动态影响”。‘visibility’的其他值不会产生影响。
这里有一些在列上设置属性的样式规则的实例。前两个规则一起实现了HTML4中值为‘cols’的“规则”属性。第三个规则使得‘totals’列为蓝色,最后两个规则展示了如何使用固定布局算法设置一个列的固定大小。

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

視覺布局模型中的表格

以視覺布局模型來說,表格可以有像是塊級元素('display: table' 的時候)或是行內級元素('display: inline-table')的行為。

表格在這兩種情況都會產生一個稱為表格包裹盒主塊盒,表格包裹盒裡包有表格盒與所有表格說明盒(以文件順序)。表格盒是包有表格裡各內部表格盒的塊級盒。表格說明盒是擁有自己內容、邊距、邊界、邊框區域的塊級盒,且使用者代理會在表格包裹盒中把表格說明盒當作一般塊盒渲染。下面描述的 'caption-side' 屬性決定了表格說明盒的配置在表格盒的前面還是後面。

若表格為塊級,則表格包裹盒是一個 'block' 盒,若表格為行級,則表格包裹盒是一個 'inline-block' 盒。表格包裹盒建立塊格式化上下文。使用者代理會使用表格盒(而不是表格包裹盒)進行 'inline-table' 的基線垂直對齊。表格包裹盒的寬度是裡面表格盒邊框邊的寬度(在 17.5.2 小節描述)。表格上 'width' 和 'height' 的百分比值相對於表格包裹盒的包含塊,而不是表格包裹盒本身。

使用者代理會把表格元素上 'position'、'float'、'margin-*'、'top'、'right'、'bottom'、'left' 屬性的計算值用在表格包裹盒而不是表格盒上 ― 其他不繼承的屬性用在表格盒而不是表格包裹盒上。(表格盒與表格包裹盒沒從表格元素得到屬性值的屬性改使用初始值。)

table_container.png
表格與上面的表格說明的配置圖。

表格說明定位與對齊

'caption-side'

取值: top | bottom | inherit
初始: top
適用於: 'table-caption' 元素
繼承:
百分比: (不適用)
媒介: 視覺
計算值: 同指定值

本屬性可以用來指定表格說明盒相對於表格盒的位置。本屬性各取值的意義如下:

top

表格說明盒的位置在表格盒之上。

down

表格說明盒的位置在表格盒之下。
注:CSS2 描述的表格說明盒的寬度與水平對齊行為跟 CSS 2.1 有所不同。CSS3 會引入該行為作為本屬性的 'top-outside' 與 'bottom-outside' 值的行為。

網頁作者可以用 'text-align' 屬性來進行表格說明內容的水平對齊。

在這個範例中,'caption-side' 屬性會將表格說明放在表格之下。表格說明盒會跟表格的父元素一樣寬,說明文字會靠左對齊。 caption { caption-side: bottom; width: auto; text-align: left }

表格內容的視覺布局

内部表格元素生成一个由内容和边框组成的矩形盒子。单元格也有内边距。内部表盒元素没有外边距。

这些盒子的可视化布局基于一个矩形、不规则的行和列组成的网格。这些盒子根据下列规则占据一系列网格单元。这些规则不适用于HTML 4或更早版本;HTML增加了其跨越行和列的限制。

  1. 每个行盒子占据网格单元的一行。同时,这些行盒子按照其在源文档中出现的顺序自上至下填充表格(即,表格占领的网格行的数目与其行元素的数目相同)。
  2. 一个行群组占据的网格单元的数目与其包含的行的数目相同。
  3. 一个列盒子占据网格单元中至少一个列。列盒子按照其出现的顺序依次排列。第一个列盒子可能会根据表格的‘direction’数据被放置在最左或最右。
  4. 一个列群组占据的网格单元的数目与其包含的列的数目相同。
  5. 单元格可能会跨越几行或几列。(即使CSS 2.1没有定义如何确定跨越的行数或列数,用户代理可能会自行理解源文档;在CSS未来的更新中可能会提供使用CSS语法表达的方法。)因此每个单元格都是一个矩形盒子,宽和高都至少包含一个网格单元。该矩形的顶行是该单元格父亲指定的行。该矩形必须尽可能的靠左,但第一列中其占据的那部分单元格不能与期待单元格盒子重叠(即,一个跨越多行的单元格在靠前的行开始),并且该单元格必须在源文档中之前所有同行单元格的右边。如果该位置可能会产生一个与靠前的行上的跨越多行的单元格重叠的跨越多列的单元格,CSS没有定义结果:实作可能会重叠这些单元格(与大部分HTML实作类似)或将之后的单元格移动的右侧以避免重叠。(此约束假定表格的‘direction’属性为‘ltr’;如果‘direction’为‘rtl’,则交换前面两句中的“左”和“右”。)
  6. 单元格盒子不会超过表格的最后一个行盒子或行群组进行扩展;用户代理必须将其缩短以符合要求。

边框折叠模型下的行、列、行群组和列群组的边缘与单元格的边框中间的假定网格线一致。(因此,在该模型下,所有的行一起没有空隙地完全覆盖表格;列亦如此。)在边框分离模型下,这些边缘与单元格的边框边缘一致。(因此,在该模型下,与‘border-spacing’属性一致,在行、列、行群组或列群组之间存在空隙。)

注:按照9.7节中的规则,表格单元格的定位和浮动将使得他们不再是表格单元格。当使用浮动时,匿名表格对象上的规则可能会产生一个匿名单元格对象。
下面的例子解释规则5。下列非法的(X)HTML片段定义了冲突的单元格:

<table>
<tr><td>1 </td><td rowspan="2">2 </td><td>3 </td><td>4 </td></tr>
<tr><td colspan="2">5 </td></tr>
</table>

用户代理可以自由地选择如左图的在视觉上重叠单元格,或如右图的移动单元格以避免重叠。
table-overlap.png
一个错误的HTML表格的两种可能的显示效果。

表格布局及透明

为了确定每个表格单元格的背景,不同的表格元素可能会被认为是六个叠加层。能被看到的表格的背景只能是其上所有层均为透明背景的一个层上设置的背景。

tbl-layers.png
表格各层图解。
(由上至下依次为:单元格、行、行群组、列、列群组、表格)
  1. 最底层是一个单独的面板,其表示表格盒子本身。和所有盒子一样,其可能是透明的。
  2. 下一层由列群组组成。每个列群组贯穿的区域的顶端是最上一行的单元格的顶端、底部是最下一行的单元格的底端、从最左侧一列的左边缘到最右一列的右边缘。其背景精确地覆盖所有源自该列群组的单元格的全部范围,即使他们跨越了列群组之外,但这些区域的差异不会影响背景图片的定位。
  3. 在列群组之上,是表示列盒子的区域。每一列的高度与列群组相同,宽度与列中的普通(跨越一列)单元格相同。其背景精确地覆盖所有源自该列的单元格的全部范围,即使他们跨越了列之外,但这些区域的差异不会影响背景图片的定位。
  4. 下一层由行群组组成。每个行群组贯穿的区域的从其第一列中最顶端单元格的左上角到其最后一列的最底部单元格的右下角。
  5. 下一层由行组成。每一行的宽度与其行群组相同,高度与行中的普通(跨越一行)单元格相同。与列相似,其背景精确地覆盖所有源自该行的单元格的全部范围,即使他们跨越了行之外,但这些区域的差异不会影响背景图片的定位。
  6. 最顶层由单元格本身组成。如图解中所示,即使所有的行都包含了相同数目的单元格,但并非所有单元格都指定了内容。在边框分离模型中(‘border-collapse’为‘separate’),如果单元格的‘empty-cells’属性的值为‘hide’,则这些‘空’单元格将穿过单元格、行、行群组、列和列群组的背景,直接显示表格的背景。

“缺失的单元格”是指那些在行/列网格中没有被元素或伪元素占据的单元格。在显示缺失的单元格时,就好像一个匿名表格单元格盒子占据了网格中它的位置。

在下面的例子中,第一行包含了四个非空单元格,但第二行仅包含了一个非空单元格。因此,在第二行中,除了该非空单元格和从第一行中穿越过来的单元格外,表格的背景穿透过来。下面的HTML代码和样式规则

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
  <HEAD>
    <TITLE>Table example</TITLE>
    <STYLE type="text/css">
      TABLE  { background: #ff0; border: solid black;
               empty-cells: hide }
      TR.top { background: red }
      TD     { border: solid black }
    </STYLE>
  </HEAD>
  <BODY>
    <TABLE>
      <TR CLASS="top">
        <TD> 1 
        <TD rowspan="2"> 2
        <TD> 3 
        <TD> 4 
      <TR>
        <TD> 5
        <TD>
    </TABLE> 
  </BODY>
</HTML>

将会被格式化为:
tbl-empty.png
空单元格在下面一行的表格。

需要注意的是,如果表格设置了“border-collapse: separate”,‘border-spacing’属性所给出的区域的背景总是表格元素的背景。参见边框分离模型

表格宽度算法‘table-layout’属性

CSS没有定义表格的“最佳”布局,因为在大多数情况下,所谓最佳因人而异。CSS定义了在布局表格时需要遵守的约束。用户代理可能会使用其希望的任何算法,并且自由的选择牺牲精确度而提高渲染速度,但这不适用于选择“固定布局算法”时。

值得注意的是本节重写了10.3章中描述的适用于计算宽度的规则。尤其是,如果表格的外边距被设为“0”且宽度被设为“auto”时,表格不会自动填充包含块。然而,一旦确定了表格‘width’的计算值(使用下面给出的算法,或者,如果恰当,使用其他的由用户代理确定的算法)就会应用10.3章的其他部分。因此,表格可以使用左右‘auto’外边框产生居中效果。

未来对CSS的更新可能会介绍使表格自动适应其包含块的方法。

'table-layout'(表格布局)

取值: auto(自动)| fixed(固定) | inherit
初始: auto
適用於: ‘table’和‘inline-table’元素
繼承:
百分比: (不適用)
媒介: 视觉
計算值: 同指定值

‘table-layout’属性控制用于布局表格单元格、行和列的算法。它的值拥有如下意义:

fixed

使用固定表格布局算法。

auto

使用自动表格布局算法。

这两个算法在下面描述。

固定表格布局

使用此(快速)算法,表格的水平布局不受单元格内容的影响;其只受表格宽度、列宽度和边框或单元格间距的影响。

表格宽度可能会使用‘width’属性精确的指定。值‘auto’(同时适用于‘display: table’和‘display: inline-table’)意味着使用自动表格布局算法。然后,如果表格是一个默认流中的块级表格(‘display: table’),即使其宽度被指定为‘auto’,用户代理亦可能会(但不是必须)使用10.3.3节中的算法来计算宽度并应用固定表格布局。

如果用户代理支持在‘width’为‘auto’时应用固定表格布局,则下列规则会创建一个比包含块窄4em的表格:
table { table-layout: fixed;
        margin-left: 2em;
        margin-right: 2em }

在固定表格布局中,按照下面的描述确定每一列的宽度:

  1. 对于一个列元素,如果其‘width’属性的值并非‘auto’,则该值设置了列的宽度。
  2. 否则,在该列中,最早一行的‘width’属性的值并非‘auto’的单元格的值确定了该列的宽度。如果单元格跨越的查过以列,列的宽度是分开的。
  3. 剩下的列评分上下的水平表格空间(减去边框或单元格间距)。

表格的宽度是表格元素‘table’属性的值和列宽度总和(加上单元格边距或边框)中的较大值。如果表格宽于列,则额外的空间将分布于各列。

如果随后各行中的列数大于表格列元素确定的数目和第一行确定的数目中的较大值,则额外的列可能不会显示。CSS 2.1没有定义需要显示它们时如何计算列和表的宽度。在使用‘table-layout: fixed’时,编码人员不应在第一行中遗漏任意一列。

在这种机制下,用户代理可以在完整的接收到第一行时就开始布局该表格。随后各行中的单元格不会影响列的宽度。内容溢出的单元格由‘overflow’属性确定如何剪裁这些溢出的内容。

自动表格布局

在此算法中(一般要求不超过两次传递),表格的宽度有列的宽度给出(包含边框)。在撰写本规范时,此算法反映了几种常见HTML用户代理的行为。用户代理必须要实现本算法来确定‘table-layout’为‘auto’时的表格布局;它们可以使用任意其他算法,即使它们会产生不同的行为。

对自动表格布局的输入必须仅包含包含块的宽度和表格及其任意后裔的内容(及其上的CSS属性)。

注:这可能会在CSS3中详细定义。

本节的剩余部分是不规范的。

由于此算法需要用户代理在确定最终布局之前访问全部内容,可能会需要多次传递,因此其效率可能非常低下。

按照下面的描述确定每一列的宽度:

  1. 计算每个单元格的最小内容宽度(MCW):格式化的内容可能会跨越多行但可能不会溢出单元格盒子。如果给单元格指定的‘width’(W)大于MCW,则W是最小单元格宽度。若值为‘auto’,则意味着MCW是最小单元格宽度。
    另外,计算每个单元格的“最大”单元格宽度:格式化内容时除非遇到明确的换行符则不换行。
  2. 对于每一列,根据近跨越该列的单元格计算最大、最小的列宽度。最小列宽度指的是拥有最大的最小单元格宽度(或与列的‘width’之间的较大值)的单元格的单元格宽度。最大列宽度指的是拥有最大的最大单元格宽度(或与列的‘width’之间的较大值)的单元格的单元格宽度。
  3. 对于每个跨越多列的单元格,叠加其跨越的列的最小宽度,它们至少应当与单元格的宽度相同。最大宽度也应当如此。如果可能,近似相同地扩大所有跨越的列的宽度。
  4. 对于每一个‘width’不为‘auto’的列群组元素,叠加其跨越的列的最小宽度,它们至少应当与列群组的宽度相同。

这给出了每一列的最大、最小的宽度。

标题宽度最小值(CAPMIN)可以通过将每个标题的最小标题外宽度计算为包含格式化为“display: block”的标题的假定表格单元格的最小内容宽度来确定。最大的最小标题外宽度就是标题宽度最小值。

列和标题宽度按照下面的描述影响最终表格宽度:

  1. 如果‘table’或‘inline-table’元素的‘width’属性拥有一个并非‘auto’的计算值(W),则使用的宽度是W、CAPMIN以及由所有列加上单元格间距或边框所确定的最小宽度(MIN)之中的最大值。如果使用的宽度大于MIN,额外的宽度应当分布在各列之中。
  2. 如果‘table’或‘inline-table’元素设置了‘width: auto’,则使用的宽度是表格的包含块宽度、CAPMIN和MIN之中的最大值,如果CAPMIN或者由列加上单元格间距或边框所确定的最大宽度(MAX)小于包含块的宽度,则使用max(MAX, CAPMIN)。

列宽度的百分比值与表格宽度相关联。如果表格设置了‘width: auto’,则百分比值表示一个在列宽度上的约束条件,用户代理应当试图满足该约束。(显然,这不总是可行:如果列的宽度为“110%”,则该约束不可能满足。)

注:在本算法中,行(以及行群组)和列(以及列群组)约束并且被约束于它们所包含的单元格的大小。设置一个列的宽度可能会间接地影响一个行的高度,反之亦然。

表格高度算法

表格的高度由‘table’或‘inline-table’元素的‘height’属性给出。其值‘auto’表示其高度是行高度加上任意单元格间距或边框的总和。它的任意的值被视为最小值。CSS 2.1没有定义‘height’属性造成表格高于其不应用该属性时的高度所产生的额外控件将如何分布。

注:CSS的未来更新可能会指定此特性。

‘table-row’元素的盒子的高度在用户代理确认该行之内的所有单元格均可用后立刻计算:其是行的计算后‘height’、行内各单元格的计算后‘height’以及单元格所需要的最小高度(MIN)之中的最大值。‘table-row’的‘height’属性的值‘auto’表示用于布局的行高是MIN。MIN取决于单元格盒子的高度和单元格盒子的对齐方式(与对行盒子高度的计算类似)。CSS 2.1没有定义在表格单元格和表格行被指定为百分比值时如何计算其高度。CSS 2.1没有定义行群组上‘height’的意义。

在CSS 2.1中,单元格盒子的高度是其内容所需的最小高度。表格单元格的‘height’属性可以行的高度(见上面),但不会影响单元格盒子的高度。

CSS 2.1没有指定指定跨越多行的单元格对行高计算的影响,但涉及的行的总高度必须足够高,以便其能够包含单元格跨域这些行。

每个表格单元格的‘vertical-align’属性确定其在行内的对齐方式。每个单元格的内容都和行本身一样,拥有基线、顶部、中部和底部。在表格上下文中,‘vertical-align’的值拥有下列意义:

baseline(基线)

单元格的基线被放置的高度与其所跨越的第一行的基线相同(查看下面对于单元格和行的基线的定义)。

top(顶部)

单元格盒子的顶部与其所跨越的第一行的顶部对齐。

bottom(底部)

单元格盒子的底部与其所跨越的最后一个的底部对齐。

middle(中部)

单元格的中央与其所跨越的行的中央对齐。

subsupertext-toptext-bottom<length><percentage>

这些值不适用于单元格;单元格对其基线对齐;

单元格的基线是该单元格内第一个内部流的行盒或表格行中首先出现的一个的基线。如果没有这样的行盒或表格行,则基线为单元格盒子的内容边缘的底部。为了确定基线,拥有滚动机制(参见‘overflow’属性)的内部流盒子必须被认为其已经滚动至源位置。值得注意的是单元格的基线可能会低于其底部边框,详见下面的例子

从单元格盒子的顶部到各个拥有‘vertical-align: baseline’的单元格的基线的最大距离被用来设置该行的基线。下面是一个例子:

cell-align.png
图示展示了表格单元格上“vertical-align”各值的效果。

单元格盒子1、2与其基线对齐。单元格盒子2拥有基线的最大高度,所以其确定了行的基线。

如果一行没有与基线对齐的单元格,则该行的基线是行内最低的单元格的底部内容边缘。

为了避免模棱两可的情况,单元格的对齐方式按照下列顺序确定:

  1. 首先定位对齐至其基线的单元格。这将确立行的基线。之后是定位“vertical-align: top”的单元格。
  2. 该行现在拥有了顶端、可能的基线、以及临时高度(由顶端到最低的已定位单元格的底部)。(查看下面关于单元格内边距的约束。)
  3. 如果剩下的与底部或中部对齐的单元格之中,任意单元格拥有大于行的当前高度的高度,则行的高度将会通过降低其底部,被增加至这些单元格中的最大值。
  4. 最后定为剩下的单元格。

小于该行高度的单元格盒子,将会获得额外的顶部或底部内边距。

本例中的单元格拥有一个低于下边框的基线:

div { height: 0; overflow: hidden; }

<table> <tr> <td> <div> Test </div> </td> </tr> </table>

列中的水平算法

单元格盒子中行级内容的水平算法可以通过在单元格上的‘text-align’属性的值来确定。

动态行列效果

‘visibility’属性在行、行群组、列和列群组元素上拥有值‘collapse’。该值会造成行或列从显示中移除,且该空白通常由其他内容可用的行或列取代。跨越与折叠的列或行相交叉的行或列的内容将被剪裁。然后,隐藏的行或列不会在其他方面影响表格的布局。这允许动态的移除表格的行或列,而不用为了列约束中的潜在变化而强制重新布局该表格。

邊框

在CSS中存在两种不同的设置表格单元格边框的模型。一种更加适合在单独单元格周围的所谓分离边框,另一种适合从表格一端到另一端的连续的边框。许多边框样式同时适用于两种模型,所以在确定使用何种模型时因人而异。

‘border-collapse’

取值: collapse(合并) | separate(分离) | inherit
初始: separate
適用於: ‘table’及‘table-caption’元素
繼承:
百分比: (不適用)
媒介: 视觉
計算值: 同指定值

该属性选择表格的边框模型。值‘separated’选择边框分离模型。值‘collapse’选择边框合并模型。这些模型将在下面描述。

边框分离模型

‘border-spacing’

取值: <长度> <长度>? | inherit
初始: 0
適用於: ‘table’及‘table-caption’元素*
繼承:
百分比: (不適用)
媒介: 视觉
計算值: 两个绝对长度
注:*) 用户代理可能还会在‘frameset’元素上应用‘border-spacing’属性。这些‘frameset’元素没有在本规范中定义,其定义自文档语言。例如,HTML4定义了一个<FRAMESET>元素、XHTML 1.0定义了一个<frameset>元素。因此,在‘frameset’元素上的‘border-spacing’属性可以被用于替代不标准的‘framespacing’属性。

长度指定了邻近单元格边框间的距离。如果指定了一个长度,则它同时给出了水平和垂直间距。如果指定了两个长度,则第一个长度给出了水平间距、第二个长度给出了垂直间距。长度不能为负值。

从表格边框到处于表格边缘的单元格的边框直接的距离是对应一侧的表格的内边距加上相应的边框间距。例如,在右侧,其距离为右内边距(padding-right)+水平边框间距(border-spacing)。

表格的宽度是从左侧内边距边缘内侧到右侧内边距边缘内侧直接的距离(包含边框间距但不包含内边距和边框)。

但是,在HTML和XHTML1中,元素的宽度是从左侧边框边缘到右侧边框边缘直接的距离。
注:在CSS中,这条特殊要求将会在用户代理样式表规则及‘box-sizing’属性的条款中定义。

在此模型下,每个单元格都拥有一个独立的边框。‘border-spacing’属性指定了相邻单元格边框直接的距离。在这些空间内,不会显示行、列、行群组及列群组的背景,而是显示表格的背景。行、列、行群组及列群组不能拥有边框(即:用户代理必须忽略这些元素的边框属性)。

下图中的表格时下列样式表的结果:

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

tbl-spacing.png
‘border-spacing’设置了一个长度值的表格。需要注意的是每个单元格都拥有其自己的边框,表格也有一个独立的边框。
空单元格周围的边框和背景:‘empty-cells’属性

‘empty-cells’

取值: show(显示) | hide(隐藏) | inherit
初始: show
適用於: ‘table-cell’元素
繼承:
百分比: (不適用)
媒介: 视觉
計算值: 同指定值

在边框分离模型中,该属性控制环绕在没有可视化内容的单元格周围的边框和背景的显示效果。空单元格以及‘visibility’属性被设为‘hidden’的单元格被认为没有可视化内容。除非单元格包含至少一个下列内容,则其为空:

  • 浮动内容(包括空元素)。
  • 内部流内容(包括空元素),但不能使被‘white-space’属性处理掉的空格。

若概述的值为‘show’,则边框和背景将被绘制在空单元格周围/之后(与普通单元格一样)。

值‘hide’意味着边框和背景将不会被绘制在空单元格周围/之后(参见17.5.1节的第6点)。此外,如果行内的所有单元格的值都是‘hide’且都没有可视化内容,则该行的高度为零,并且该行的垂直边框间距仅在一侧出现。

下面的规则会在所有单元格周围绘制边框和背景:

table { empty-cells: show }

边框合并模型

在边框合并模型中,可以指定边框将会环绕单元格、行、行群组、列和列群组的全部或部分。HTML的的边框的“rules”属性可以指定它。

边框居中在单元格直接的网格线上。用户代理必须找到一个一致性规则来在奇数离散单元的情况向四舍五入。

下面的图表展示了表格宽度、边框宽度、内边距和单元格宽度之间的关系。它们的关系有下面的等式给出,它适用于表格的每一行:

行宽度 = (0.5 * 边框宽度0) + 左内边距1 + 宽度1 + 右内边距1 + 边框宽度1 + 左内边距2 + … + 右内边距n + (0.5 * 边框宽度n)

“n”是行内单元格的数目;“左内边距i”和“右内边距i”指的是第i个单元格的左、右内边距;“边框宽度i”指的是在第i个单元格和第i+1个单元格直接的边框。

用户代理必须通过检查表格第一行中的第一个和最后一个单元格来计算表格的初始左、右边框宽度。表格的左边框宽度是第一个单元格折叠后的左边框的一半;表格的右边框是最后一个单元格折叠后右边框的一半。如果随后各行中的折叠后左、右边框较大,则额外宽度将移除的表格的外边距区域。

表格的顶部边框宽度可以通过检查所有与表格的顶部边框折叠的单元格来计算。表格的顶部边框宽度等于折叠后顶部边框最大值的一半。表格的底部边框宽度可以通过检查所有与表格的底部边框折叠的单元格来计算。表格的底部边框等于折叠后底部边框最大值的一半。

在确定表格是否会溢出其祖先时,需要考虑泄露到外边距的边框(参见‘overflow’)。

tbl-width.png
图示展示了单元格及其边框、内边距的宽度。
上方由左至右:边框宽度、内边距、单元格宽度、内边距、边框宽度、内边距、单元格宽度、内边距、边框宽度、内边距、单元格宽度、内边距、边框宽度
下方由左至右:表格边框宽度、行宽度、(网格线)、表格边框宽度

需要注意的是,在此模型下,表格的宽度包括表格边框的一半。同样,在此模型下,表格没有内边距(但拥有外边距)。

CSS 2.1没有定义表格元素背景的边缘位置。

解决边框冲突

在边框合并模型中,每个单元格的每个边缘处的边框都可能会由在边缘处接触的不同元素上的边框属性设置(单元格、行、行群组、列、列群组和表格本身),并且这些边框可能会在宽度、样式和颜色上改变。处理这些问题的经验是在每个边缘处选择最“显眼”的边框样式,但如何其样式中出现了‘hidden’则无条件的消去边框。

下列规则可以确定在冲突的时候会选择哪种边框样式:

  1. ‘border-style’为‘hidden’的边框优先于所有其他冲突的边框。拥有此值的边框会抑制在此位置上的所有边框。
  2. 样式为‘none’的边框的优先级最低。仅当所有与该边缘接触的元素的边框属性均为‘none’时,该边框才会被忽略(但是需要注意的是‘none’是边框样式的默认值)。
  3. 如果边框的样式均不为‘hidden’且至少一个不为‘none’,则较宽的边框有限与较窄的。如果几个边框拥有相同的‘border-width’值,则边框样式的优先顺序为:‘double’、‘solid’、‘dashed’、‘dotted’、‘ridge’、‘outset’、‘groove’及最低的‘inset’。
  4. 如果边框样式中仅有颜色不同,设置在单元格上的样式优先于设置在行上的,之后依次为设置于行群组、列、列群组和最后的表格上的样式。如果两个相同类型的元素发生了冲突,则靠左(表格的‘direction’为‘ltr’;如果为‘rtl’则靠右)、靠上的元素优先级高。
下列实例阐述了这些优先级规则的应用。样式表如下:

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

HTML源如下:

<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="cell5"> 5 <TD class="cell6"> 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>

其结果如下:

tbl-border-conflict.png
边框合并表格的实例。
下面是隐藏折叠边框的实例:
CSStbl3.png
拥有连个忽略的内部边框的表格实例。

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>

边框样式

‘border-style’属性的某些值在表格中拥有和其他元素不同的意义。在下面的列表中,这些值将以型号标出。

none

无边框

*hidden

与‘none’相同,但在边框合并模型下,还会抑制其他边框(参见边框冲突节)。

dotted

边框为一系列点。

dashed

边框为一系列短线段。

solid

边框为一条单线段。

double

边框为两条实线。两条线和期间空白的总和等于‘border-width’的值。

groove

边框看上去像是雕刻在画布上。

ridge

与‘groove’相反:边框看上去像是漂浮在画布之上。

*inset

边框分离模型下,边框使得整个盒子看上去像是嵌入在画布之内。在边框合并模型下,与‘ridge’相同。

*outset

边框分离模型下,边框使得整个盒子看上去像是漂浮在画布之上。在边框合并模型下,与‘groove’相同。