刚看到table layout表单布局是不是不想接触,不过本章不是关于怎么使用table来布局的,而是来看看table自己是怎么借助CSS来布局的,因为这比它看上去的要复杂的多。
table表单跟其他布局相比是有点奇怪的,因为他会将元素大小和其他元素大小做关联。例如所有一行的cell高度都是一样的,width也是这样。
格式化Table表单
首先也是最重要的就是了解下CSS是怎么处理和渲染内部table元素的,其中一个关键点就是没有margin。
除了这个意外,排布table还有6个基本的规则,而这些规则的基石就是grid cell。也就是说table排布从某种意义上说是基于grid布局的:
而这些grid cell都是理论上创建的,也就是说这些样式是无法通过DOM获取的,他们只是用来描述表单如何渲染的。
Table排布规则:
- row的盒子包含了一整行的grid cell。自上而下渲染。
- row group 的盒子和row 盒子一样包含相同的grid cell。
- column box 可以包含一个或多个column的grid cell,从左往右排列。
- column group 的盒子和column 盒子一样包含相同的grid cell。
- 虽然cell可以span多行和多列,不过CSS自己没有定义如何实现,依赖浏览器来做
- cell盒子无法超过最底部行的返回,不会自动扩展
table 的display值
我们其实默认在html其实还涉及不到这些字段,因为已经内定了不同的标签,比如tr,td等。而对于其他的超文本语言,例如xml的话这就很有必要自定义不同的table类型:
- table: 生成一个block的table
- inline-table: 生成一个inline的table
- table-row:表征table的一行,对应于tr
- table-row-group:可以包含多行的group,对应于html的tbody
- table-header-group:表示table头部的row group,对应于thead
- table-footer-group:跟table-header-group类似,对应于tfoot
- table-column:在CSS中不会渲染,对应于col
-table-column-group:跟table-column类似,也不渲染,对应于colgroup
-table-cell:代表了单个cell,类似于th和td
整个table组件以横向组织位置,纵向内容为辅,其中每个column的元素支持四个属性:border,background,width和visibility。
Table Layer
table的渲染从下往上由下面几层组成:
table说明
一般table在上面或是下面都要有个说明,可以通过caption-side来定位:
caption {background: #B84; margin: 1em 0; caption-side: top;}
table {color: white; background: #840; margin: 0.5em 0;}
Table Cell Borders
css中好办了两种不同的border处理方式,核心是到底要不要合并相邻的border,通过border-collapse来设置:
首先看下separate的例子:
table {border-collapse: separate;}
td {border: 3px double black; padding: 3px;} tr:nth-child(2) td:nth-child(2) {border-color: gray;}
<table cellspacing="0"> <tr>
<td>cell one</td>
<td>cell two</td> </tr>
<tr>
<td>cell three</td> <td>cell four</td>
</tr>
</table>
既然中间有gap,那么一定有属性来定义gap的宽度,这个就是border-spacing:
table {border-collapse: separate; border-spacing: 5px 8px; padding: 12px; border: 2px solid black;}
td { border: 1px solid gray;}
td#squeeze {border-width: 5px;}
另外对于空的cell是否显示,可有对应的属性:
合并的cell border
合并border本身存在一系列的规则,结构示意图如下图:
下面总结了不同的使用特点:
table {border-collapse: collapse;
border: 3px outset gray;}
td {border: 1px solid gray; padding: 0.5em;} #r2c1, #r2c2 {border-style: hidden;}
#r1c1, #r1c4 {border-width: 5px;}
#r2c4 {border-style: double; border-width: 3px;} #r3c4 {border-style: dotted; border-width: 2px;} #r4c1 {border-bottom-style: hidden;}
#r4c3 {border-top: 13px solid silver;}
Table设置大小
table的宽度分为两类,固定的宽度布局,还有自动计算宽度的布局。不过不管哪种,高度都是自动计算的。
而控制这种不同的属性就是table-layout:
但从渲染来说,固定的宽度比自动计算的要快不少,因为宽度完全不依赖于table cell的内容。
来看个固定的例子:
table {table-layout: fixed; width: 400px; border-collapse: collapse;}
td {border: 1px solid;} col#c1 {width: 200px;} #r1c2 {width: 75px;} #r2c3 {width: 500px;}
<table>
<colgroup> <col id="c1"><col id="c2"><col id="c3"><col id="c4"> </colgroup> <tr>
<td id="r1c1">1-1</td> <td id="r1c2">1-2</td> <td id="r1c3">1-3</td> <td id="r1c4">1-4</td>
</tr> <tr>
<td id="r2c1">2-1</td> <td id="r2c2">2-2</td> <td id="r2c3">2-3</td> <td id="r2c4">2-4</td>
</tr> <tr>
<td id="r3c1">3-1</td> <td id="r3c2">3-2</td> <td id="r3c3">3-3</td> <td id="r3c4">3-4</td>
</tr> <tr>
<td id="r4c1">4-1</td> <td id="r4c2">4-2</td> <td id="r4c3">4-3</td> <td id="r4c4">4-4</td>
</tr>
</table>
然后看下自动auto计算的,这个其实特别常见,也是html默认的方式。有意思的是不需要把table的table-layout设定为auto,而只要width设为auto就会触发了。
table {table-layout: auto; width: auto; border-collapse: collapse;}
td {border: 1px solid; padding: 0;} col#c3 {width: 25%;}
#r1c2 {width: 40%;}
#r2c2 {width: 50px;}
#r2c3 {width: 35px;} #r4c1 {width: 100px;} #r4c4 {width: 1px;}
对齐
table cell的对齐可以使用vertical-align来定义:
table {table-layout: auto; width: 20em; border-collapse: separate; border-spacing: 3px;} td {border: 1px solid; background: silver;
padding: 0;}
div {border: 1px dashed gray; background: white;} #r1c1 {vertical-align: top; height: 10em;}
#r1c2 {vertical-align: middle;}
#r1c3 {vertical-align: bottom;}
还有一个baseline对齐:
小结
哪怕你以前对tale已经很熟了,但是其背后的布局机制还是很复杂的。在HTML中,CSS的table是基于行排布的,不过也兼容列的排布。table 的layout超越了html的限制,可以应用在更广阔的使用场景中。