表格式化
我们先来看看组装表的基本方法,并了解表中的元素相互之间有什么关系。这称为表格式化。
表的视觉编排
CSS对于表元素和内部表元素有很分明的界限。在CSS中,内部表元素生成矩形框,这些框有内容,内边距和边框,但是没有外边距。因此,不能通过指定外边距来定义单元格之间的间隔。如果试图对单元格、行或任何其他内部表元素应用外边距,CSS兼容浏览器只会将其忽略(只有总标题例外)。
使用display的不同值来表示元素在表中不同的角色:
- table:这个值指定一个元素定义了一个块级表。它定义了一个生成块框的矩形块。
- inline-table:这个值指定一个元素定义了一个行内级表。这说明,该元素定义了一个生成行内框的矩形块,与之最接近的非表值是inline-block。最接近的HTML元素为table。不过,默认情况下HTML表不是行内元素。
- table-row:这个值指定一个元素是一个单元格的行。相应的HTML元素是tr元素。
- table-row-group:这个值指定一个元素是一个或多个行的组。相应的HTML值是tbody。
- table-header-group:这个值与table-row-group非常相似,只是视觉格式化方面有所不同,标题行组总是在所有其他行和行组之前显示。打印时,如果一个表需要多页打印,用户代理可以在各页顶端重复标题行,规范没有定义如果为多个元素指定table-header-group值会发生什么情况。标题组可以包含多个行。与之对应的HTML元素是thead。
- table-footer-group:这个值与table-header-group很类似,不过脚注行组总是在所有其他行之后显示,如果最下面有页脚标,要在该总标题之前显示。打印时,如果一个表需要多页打印,用户代理可以在各页底端重复页脚行。规范没有定义如果为多个元素指定table-foo,ter-group值会有什么结果。与之对应的HTML元素是tfoot。
- table-column:这个值声明元素描述了一个单元格的列。按CSS的术语来说,有这个display值的元素并不显示,就好像它的display值为none—样。之所以存在这个值,主要是为了帮助定义列中单元格的表示。相应的HTML元素是col元素。
- table-column-group:这个值声明一个元素是一个或多个列的组。类似于table-column元素,table-column-group元素也不显示,不过这个值有助于定义列组中
元素的表示。相应的HTML元素是colgroup元素。 - table-cell:这个值指定一个元素表示表中的单个单元格。HTML元素th和td都属于table-cell元素。
- table-caption:这个值定义一个表的总标题。CSS没有定义如果多个元素的display值都为caption时会发生什么情况,不过CSS确实明确地警告,“......创作人员不要在一个表或行内表元素中放多个有display: caption的元素。”
所以,其实我们平时用的td啊tr啊其实都是因为用户代理里面已经预先定义好了这些,所以我们才没有需要处理这些复杂的display值的。
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;}
以行为主
CSS将其表模型定义为“以行为主”。换句话说,这个模型假设创作人员创建的标记语言会显式声明行,而列是从单元格行的布局推导出来的。因此,第一列由各行中的第一个单元格组成,第二列则由各行中第二个单元格组成,依此类推。
匿名表对象
标记语言中可能未包含足够的元素,以至于无法按CSS的定义充分表示表,也可能创作人员没有加入所有必要的元素。比如tbody一般我们都不写,由用户代理帮忙插入。
表层
为了完成表的显示,CSS定义了6个不同的层,分别用来放置表的不同方面。有底至顶分别是:table、column groups、columns、row groups、rows、cells。每一层的元素都绘制在上一层之上。
表单元格边框
在表格中有两种截然不同的边框模型。如果单元格相互之间是分隔的,就是分隔边框模型在起作用。另一种是合并边框模型,采用这种模型,单元格之间没有可见的间隔,单元格边框会相互合并。
border-collapse:collapse | separate | inherit
分隔单元格边框
采用这种模型,表中的每个单元格都与其他单元格分开一定距离,而且单元格的边框彼此不会合并。
如果能定义分隔边框,就应该有办法使用CSS改变单元格之间的间隔。幸运的是,确实有这样的办法。
border-spacing:(length)(length)? | inherit
<table>
<tr>
<td>cell one</td>
<td>cell two</td>
</tr>
<tr>
<td>cell three</td>
<td>cell four</td>
</tr>
</table>
table {
border-collapse: separate;
border-spacing: 10px 5px;
td {
border: 3px double black;
padding: 3px;
}
}
处理空单元格
对于没有内容的单元格,使用这个属性来控制。
empty-cells:show | hide | inherit
合并单元格边框
在这种情况下,table元素是不能有内边距的,也就是说,表的外围边框与其最外单元格的边界之间不会有间隔。单元格之间也不会有间隔,相邻的边框会合并为一个。至于怎么合并,并不是左边的画一半右边的画一半。而是哪边胜出画那边,胜出的规则:
- 如果某个合并边框的border-style为hidden,它会优先于所有其他合并边框。这个位置上的所有边框都隐藏。
- 如果某个合并边框的border-style为none,它的优先级最低。这个位置上不会画出该边框,除非所有其他合并边框的border-style值都是none。
- 如果至少有一个合并边框的border-style值不是none,而且所有合并边框的border-style值都不是hidden,则窄边框不敌更宽的边框。
- 如果多个合并边框有相同的宽度,则会考虑边框样式,并采用以下顺序(从最优先到最不优先):double、solid、dashed、dotted、ridge、outset、groove、inset。
- 如果合并边框的样式和宽度都一样,但是颜色不同,则按下表烦序使用元素的颜色(从最优先到最不优先):cell、row、row group、column、column group, table。
- 如果合并边框来自相同类型的元素,如两个有相同样式和宽度但不同颜色的行边框,则颜色取最上最左边框的颜色。
表大小
下面需要了解如何确定表及其内部元素的大小。关于确定表的宽度,有两种不同的方
法:固定宽度布局和自动宽度布局。不论使用何种宽度算法,高度都会自动计算。
宽度
两种不同的方法:
table-layout:auto | fixed | inherit
尽管这两个模型针对一个特定表布局可能有不同的结果,但二者之间最显着的差异是速度。使用固定宽度表布局时,相对于自动宽度模型,用户代理可以更快地计算出表的布局。
固定布局
- width属性值不是auto的所有列元素会根据width值设置该列的宽度。
- 如果一个列的宽度为auto,不过表首行中位于该列的单元格width不是auto,则根据该单元格宽度设置此列的宽度。如果这个单元格跨多列,则宽度在这些列上平均分配。
- 在以上两步之后,如果列的宽度仍为auto,会自动确定其大小,使其宽度尽可能相等。
- 此时,表的宽度设置为表的width值或列宽度之和(取其中较大者)。如果表宽度大于其列宽总和,将二者之差除以列数,再把得到的这个宽度增加到每一列上。
这种方法的速度很快,因为所有列宽度都由表的第一行定义。首行后所有行中的单元格都根据首行所定义的列宽确定大小。后面这些行中的单元格不会改变列宽,这意味着为这些单元格指定的width值都会被忽略。如果一个单元格的内容无法放下,该单元格的overflow值将决定单元格内容是剪裁。可见还是生成一个滚动条。
自动布局
为什么自动布局比较慢,因为在用户代理査看完表的所有内容之前无法确定表的布局。也就是说,自动布局要求用户代理毎得到一个新单元格时都完成整个表的布局。
步骤:
- 对于一列中的各个单元格,计算最小和最大单元格宽度。
a. 确定显示内容所需的最小宽度。要记住,内容可以流入多行,不过不能超出单元格框。如果单元格的width值大于最小可能宽度,则把最小单元格宽度设置为该width值。如果单元格的width值为auto,最小单元格宽度则设置为最小内容宽度。
b. 对于最大宽度,要确定完全显示内容而且不包括换行符所需的宽度(除非明确要求,例如指出可以有br元素),这个值就是最
大单元格宽度。 - 对于各一列,计算最小和最大列宽。
a. 列的最小宽度由该列中所有单元格的最小单元格宽度的最大值确定。如果为该列指定的width值大于列中所有最小单元格宽度,最小列宽则设置为这个width 值。
b. 要计算最大宽度,取该列中所有单元格的最大单元格宽度的最大值。如果已经为列指定了一个width值,而且大于该列中的所有最大单元格宽度,最大列宽则设置为该width值。这两种行为改写了传统的HTML表行为,对于HTML 表,会强制列扩展为与其最宽的单元格同宽。 - 如果一个单元格跨多列,最小列宽之和必须等于这个跨列单元格的最小单元格宽度。类似地,最大列宽之和必须等于跨列单元格的最大宽度。如果列宽之和与单元格宽度有差距,用户代理会把这个差距在所跨的列上平均分配。
此时,用户代理已经确定了各列可能是多宽或多窄。有了这个信息,可以再真正得出表的宽度。这个过程如下:
- 如果表的计算宽度值不是auto,将这个计算表宽度值与所有列宽再加上所有边框和单元格间隔之和相比较(设置为百分数宽度的列往往在此时计算具体宽度)。二者中较大的一个就是表的最终宽度。如果表的计算宽度值大于列宽、边框和单元格间隔之和,所有列的宽度都会增加一个相等的量,使得刚好将表完全填充。
- 如果表的计算宽度值为auto,通过将列宽、边框和单元格间隔相加来确定表的最终宽度。这说明表的宽度只能恰好显示其容,而不能有多余,这类似于传统的HTML表。设置为百分数宽度的列会以这个百分数作为一个限制,不过用户代理有可能并不满足这个限制。
高度
如果表的高度是auto,其高度则是表中所有行的行高再加上所有边框和单元格间隔的总和。
显式设置高度的时候,行为在CSS中并没有一个标准。貌似是可以相对于auto时的值更大,用户代理会把增加出的高度分到各行。更小的话就不行了。
对齐
水平:text-align
垂直:vertical-align