HTML中表格的主要用途是以网格的形式显示二维数据、在HTML的早期版本中,却常常用表格来控制页面布局,创造出类似于今天CSS栅格的效果。
大家好,我是阿闽。几天没更前端知识,主要是为了准备这次放个大招,把关于表格的元素一股脑讲了。顶得上前几天的总写作任务。
表格
如何创造一个表格
在HTML中创建一个表格,只需要一个table
元素。其次,为了在表格中建立单元格、表格行和表格列等概念还需要借助于td
、th
、tr
、col
等元素。下面先介绍这些元素。
table元素
元素 | table |
---|---|
元素类型 | 流元素 |
允许具有的父元素 | 任何可以包含流元素的元素 |
局部属性 | border |
内容 | caption colgroup thead tbody tfoot tr th td |
标签用法 | 开始标签和结束标签 |
默认样式 | tr { display: table-row; vertical-align: inherit; border-color: inherit;} |
单独的一个table
元素只是创建了一个表格,但储存具体表格信息的离不开它包含的tr
、td
等元素。
tr元素
它代表表格中的行,即"table row"。
元素 | tr |
---|---|
元素类型 | 无 |
允许具有的父元素 | table thead tfoot tbody |
局部属性 | 无 |
内容 | th td |
标签用法 | 开始标签和结束标签 |
默认样式 | tr { display: table-row; vertical-align: inherit;} |
td元素
它就是表格中的一个普通单元格,即“table data cell”
元素 | td |
---|---|
元素类型 | 无 |
允许具有的父元素 | tr |
局部属性 | colspan rowspan headers |
内容 | 流内容 |
标签用法 | 开始标签和结束标签 |
默认样式 | tr { display: table-row; vertical-align: inherit;} |
局部属性:
colspan
rowxpan
在制作不规则表格中讲解;
headers
在将表头与单元格关联起来。
简短的代码示例
有了这三个元素,就能够组装一个最简单的表格:
<!-- 各编程语言和公认的诞生年份对应简表 -->
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>一个最简单的表格</title>
<style type="text/css">
#lang > td{
border: 1px dashed red;
color: blue;
background: #d005;
}
#year > td{
border: 1px dashed blue;
color: greenyellow;
background: #00d5;
}
#table td{
text-align: center;
}
</style>
</head>
<body>
<div style="display: flex;
align-content: center;
justify-content: center;">
<table style="background: yellow;"
border="10px"
id="table">
<tr id="lang">
<td>Python</td>
<td>Java</td>
<td>Rust</td>
<td>C/C++</td>
<td>JavaScript</td>
</tr>
<tr id="year">
<td>1989年</td>
<td>1995年</td>
<td>2012年</td>
<td>1970年/1979年</td>
<td>1995年</td>
</tr>
</table>
</div>
</body>
</html>
运行结果:
在这段代码中,每个td
标记了每个表格栏的内容,而tr
将五个td
组织成表格table
中的一行。在浏览器中也确实显示成一行。
这段代码中也使用了table
的border
属性,此属性的效果在MDN开发者社区的解释是:
This integer attribute defines, in pixels, the size of the frame surrounding the table. If set to 0, the frame attribute is set to void.
这个整数属性用像素值表示table
的外边框大小,如果设置为0,则边框设置为无。
该属性可以用CSS实现。
假设某table
的border
属性值为10,等效于其添加了如下样式:
table {
border: 10px outset gray;
}
添加表头单元格
表头单元格可以用来区分数据和对数据的说明。在HTML中用th
元素表示,亦即“table head”。
th元素
元素 | th |
---|---|
元素类型 | 无 |
允许具有的父元素 | tr |
局部属性 | colspan 、rowspan 、scope 、headers |
内容 | 短语内容 |
标签用法 | 开始标签和结束标签 |
默认样式 | th { display: table-cellvertical-align: inherit; font-weight: bold; text-align: center; } |
局部属性:
colspan
和rowspan
制作不规则表格中讲解;
scope
headers
在将表头与单元格关联起来中讲解;
代码示例
下面我们为上面的表格添加表头元素来补充对表格数据的说明:
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>一个最简单的表格</title>
<style type="text/css">
#lang > td{
border: 1px dashed red;
color: blue;
background: #d005;
}
#year > td{
border: 1px dashed blue;
color: greenyellow;
background: #00d5;
}
#table td{
text-align: center;
}
</style>
</head>
<body>
<div style="display: flex;
align-content: center;
justify-content: center;">
<table style="background: yellow;
border: 10px outset gray;"
border="10"
id="table">
<tr id="lang">
<th>编程语言</th>
<td>Python</td>
<td>Java</td>
<td>Rust</td>
<td>C/C++</td>
<td>JavaScript</td>
</tr>
<tr id="year">
<th>开发年份</th>
<td>1989年</td>
<td>1995年</td>
<td>2012年</td>
<td>1970年/1979年</td>
<td>1995年</td>
</tr>
</table>
</div>
</body>
</html>
运行结果:
为表格添加结构
基本表格有了,但现在遇到一个问题。在设置表格的时候就会发现,要区别全是th
元素的行中的th
元素和与数据单元td
混在一行中的th
元素并不容易。全是th
的行和仅包含少数th
的行是有不同语义的,而且通常需要使用不同的CSS样式来区分。HTML为全是th
的行增加了标签。
thead元素
thead
元素表示整个表格的头部,通常全是th
元素,亦即“table head”(与上面那个“table head”语义不同,可以理解为前面那个表示表格的小标题,而下面这个是上面那个标题的集合)
元素 | thead |
---|---|
元素类型 | 无 |
允许具有的父元素 | table |
局部属性 | 无 |
内容 | tr |
标签用法 | 开始标签和结束标签 |
默认样式 | thead { display: table-header-group; vertical-align: middle; border-color: inherit; } |
有了头,就要有身体,表格的“身体”对应的就是tbody元素
tbody元素
元素 | tbody |
---|---|
元素类型 | 无 |
允许具有的父元素 | table |
局部属性 | 无 |
内容 | tr |
标签用法用法 | 开始标签和结束标签 |
默认样式 | tbody { display: table-row-group; vertical-align: middle; border-color: inherit; } |
tbody
表示构成表格主体的所有行,相对于表示表格头的thead
。即使没有用到tbody
,大部分浏览器在处理table
的时候都会自动插入tbody
。因此完全根据文档中的表格结构来设计CSS选择器可能不管用。如:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>被隐式插入的tbody</title>
<style type="text/css">
#directly > .name, #indirectly .name{
border: 3px blue solid;
background: #00d3;
}
td, th{
outline: 1px black dashed;
}
#directly > .birthday, #indirectly .birthday{
border: 3px red solid;
background: #d003;
}
table{
border: 10px black solid;
}
div:not(#caption){
display: flex;
align-content: center;
justify-content: center;
margin-bottom: 50px;
border: 10px transparent solid;
border-radius: 30px;
background: #0003;
}
#caption{
font-size: 80px;
font-weight: bolder;
color: orangered;
text-align: center;
padding: 50px 0;
}
</style>
</head>
<body>
<div id="caption">
直接后代与间接后代比较
</div>
<div>
<table id="directly">
<tr class="name">
<th>大牛称呼</th><td>爱因斯坦</td><td>牛顿</td><td>霍金</td>
</tr>
<tr class="birthday">
<th>出生日</th><td>1879年3月14日</td><td>1643年1月4日</td><td>1942年1月8日</td>
</tr>
</table>
</div>
<div>
<table id="indirectly">
<tr class="name">
<th>大牛称呼</th><td>爱因斯坦</td><td>牛顿</td><td>霍金</td>
</tr>
<tr class="birthday">
<th>出生日</th><td>1879年3月14日</td><td>1643年1月4日</td><td>1942年1月8日</td>
</tr>
</table>
</div>
</body>
</html>
有头有身体,不增加个表脚怎么行!幸好,HTML为我们贴心地准备了tfoot
作为表脚。
tfoot元素
元素 | tfoot |
---|---|
元素类型 | 无 |
允许具有的父元素 | table |
局部属性 | 无 |
内容 | tr |
标签用法 | 开始标签和结束标签 |
默认样式 | tfoot { display: table-footer-group; vertical-align: middle; border-color: inherit; } |
在HTML5之前,tfoot
只能出现在tbody
(如果省略tbody
,则为第一个tr
)之前(脚在身体前面,奇怪吗)。在HTML5中则可以把tfoot
放在tbody
元素之后或最后一个tr
之后,这与浏览器显示表格的方式更为一致。用模板生成HTML代码时把tfoot
放在tbody
之前通常更方便一些,而手工编写HTML代码时把tfoot
放在tbody
之后则更自然一些。
thead、tbody、tfoot示例
<!DOCTYPE HTML>
<html lang="ch">
<head>
<meta charset="utf-8">
<title>tfoot示例</title>
<style type="text/css">
div{
display: flex;
align-content: center;
justify-content: center;
}
thead{
background: #d003;
border: 2px solid red;
}
tbody{
background: #0d03;
border: 2px solid green;
}
tfoot {
background: #00d3;
border: 2px solid blue;
}
td, th{
text-align: center;
}
</style>
</head>
<body>
<div>
<table>
<thead>
<tr>
<th>国家</th><th>人口</th><th>领土面积</th>
</tr>
</thead>
<tbody>
<tr>
<td>中华人名共和国</td><td>1411780000</td><td>960万平方公里</td>
</tr>
<tr>
<td>印度</td><td>1354051854</td><td>298万平方公里</td>
</tr>
<tr>
<td>美国</td><td>326766748</td><td>937万平方公里</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>综合</th><td>2798497802</td><td>2195平方公里</td>
</tr>
</tfoot>
</table>
</div>
</body>
</html>
制作不规则表格
大多数表格都是简单的网格形式,但也有表格单元跨越多行或多列的,如何用HTML制作这种表格呢?
对于任何一个单元格元素,即th
或td
,欲跨越若干行或若干列,我们只需设置它们的colspan
属性和rowspan
属性即可。
colspan
为一个正整数,指定设置该属性的单元格的宽应为几列。
rowxspan
为一个正整数,指定设置该属性的单元格的高应为几行。
在表格中,一个tr
创建一行,每个单元格元素向行中从左至右依次填充它们的colspan
列。到了下一行,若上一行有单元格元素的rowspan
值大于等于2,则其将占据本行的从其被放置的首列到之后的总共colspan
列。
枯燥的描述不易看懂,我们来看看实际代码
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>跨越多行或多列的单元格</title>
<style>
h1{
text-align: center;
}
div{
display: flex;
align-content: center;
justify-content: center;
}
td, th, tbody, thead, tfoot{
border: 2px solid black;
text-align: center;
}
</style>
</head>
<body>
<h1>
BJ40参数配置表
</h1>
<div>
<table>
<thead>
<th colspan="2">条目</th><th>BJ40</th>
</thead>
<tbody>
<tr>
<th rowspan="6">尺寸参数</th><td>整车长(mm)</td><td>4350(含备胎)</td>
</tr>
<tr>
<td>整车宽(mm)</td><td>4350(含备胎)</td>
</tr>
<tr>
<td>整车高(mm)</td><td>1797(最大质量状态)/ 1884(整车整备质量状态)</td>
</tr>
<tr>
<td>轴距(mm)</td><td>2450</td>
</tr>
<tr>
<td>前轮距(mm)</td><td>1530</td>
</tr>
<tr>
<td>后轮距(mm)</td><td>1530</td>
</tr>
<tr>
<th rowspan="2">质量参数</th><td>整备质量(kg)</td><td>1830</td>
</tr>
<tr>
<td>最大设计质量(kg)</td><td>1830</td>
</tr>
<tr>
<th rowspan="7">整车性能</th><td>最高车速(km/h)</td><td>150</td>
</tr>
<tr>
<td>最大爬坡度</td><td>60%</td>
</tr>
<tr>
<td rowspan="2">最小离地间隙(最大总质量状态)(mm)</td><td rowspan="2">210</td>
</tr>
<tr></tr>
<tr>
<td>接近角</td><td>37°</td>
</tr>
<tr>
<td>离去角</td><td>33°</td>
</tr>
<tr>
<td>纵向通过角</td><td>24°</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
把表头与单元格关联起来
td
和th
元素定义了headers
属性,它可以供屏幕阅读器和其他残障辅助技术用来简化对表格的处理。headers
属性的值可以设置为一个或多个th
单元格的id
。
代码示例:
<!DOCTYPE HTML>
<html lang="ch">
<head>
<meta charset="utf-8">
<title>关联表头</title>
<style type="text/css">
h1 {
text-align: center;
}
div {
display: flex;
align-content: center;
justify-content: center;
}
table *{
border: 2px solid blue;
color: orange;
background: #0dd3;
font-size: 40px;
text-align: center;
}
</style>
</head>
<body>
<h1>
考试时间安排(关联表头版)
</h1>
<div>
<table>
<thead>
<tr>
<th colspan="2" id="time">时间</th>
<th id="object">科目</th>
</tr>
</thead>
<tbody>
<tr>
<th rowspan="3" id="morning">上午</th>
<td headers="morning time">7:00 --- 9:00</td>
<td headers="morning object">语文</td>
</tr>
<tr>
<td headers="morning time">9:20 --- 10:20</td>
<td headers="morning object">地理</td>
</tr>
<tr>
<td headers="morning time">10:40 --- 11:40</td>
<td headers="morning object">生物</td>
</tr>
<tr>
<th id="afternoon" rowspan="2">下午</th>
<td headers="afternoon time">2:10 --- 4:10</td>
<td headers="afternoon object">英语</td>
</tr>
<tr>
<td headers="afternoon time">4:30 --- 6:00</td>
<td headers="afternoon object">政治</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
另外th
还有一个scope
属性,它也是起到语义提示的作用。具体解释看Mozilla开发者网站。
为表格添加标题
表格通常有一个标题,概括它是什么表格。前例中我们主要通过h1
元素代替这个标题,但语义的紧密性不强。幸而HTML中有专门作为表格标题的标签。
caption元素
元素 | caption |
---|---|
元素类型 | 无 |
允许具有的父元素 | table |
内容 | 流内容(但不能是table ) |
标签用法 | 开始标签和结束标签 |
默认样式 | caption { display: table-caption; text-align: center; } |
下面我们将丄例的caption
换成h1
重写:
<!DOCTYPE HTML>
<html lang="ch">
<head>
<meta charset="utf-8">
<title>关联表头</title>
<style type="text/css">
h1 {
text-align: center;
}
div {
display: flex;
align-content: center;
justify-content: center;
}
table *{
border: 2px solid blue;
color: orange;
background: #0dd3;
font-size: 40px;
text-align: center;
}
</style>
</head>
<body>
<div>
<table>
<caption>
考试时间安排(关联表头版)
</caption>
<thead>
<tr>
<th colspan="2" id="time">时间</th>
<th id="object">科目</th>
</tr>
</thead>
<tbody>
<tr>
<th rowspan="3" id="morning">上午</th>
<td headers="morning time">7:00 --- 9:00</td>
<td headers="morning object">语文</td>
</tr>
<tr>
<td headers="morning time">9:20 --- 10:20</td>
<td headers="morning object">地理</td>
</tr>
<tr>
<td headers="morning time">10:40 --- 11:40</td>
<td headers="morning object">生物</td>
</tr>
<tr>
<th id="afternoon" rowspan="2">下午</th>
<td headers="afternoon time">2:10 --- 4:10</td>
<td headers="afternoon object">英语</td>
</tr>
<tr>
<td headers="afternoon time">4:30 --- 6:00</td>
<td headers="afternoon object">政治</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
处理列
前面介绍了表格的填充过程,HTML中的表格是基于行的。单元格的定义都要放在tr
中,而表格则是一行一行地创建出来的。因此对列应用样式有点不方便,对于包含不规则单元格的表格更是如此。这个问题的解决方法是使用colgroup
和col
元素。colgroup
代表一组列。
colgroup元素
元素 | colgroup |
---|---|
元素类型 | 无 |
允许具有的父元素 | table |
局部属性 | span |
内容 | col |
标签用法 | 开始标签和结束标签 |
默认样式 | colgroup { display: table-column-group; } |
colgroup
包含列,即col
元素
col元素
元素 | col |
---|---|
元素类型 | 无 |
允许具有的父元素 | colgroup |
局部属性 | span |
内容 | 无 |
标签用法 | 虚元素形式 |
默认样式 | col { display: table-column; } |
colgroup和col元素讲解
对于colgroup
元素,我们可以结合tr
理解。原本的文档中编写表格用的是行优先的逻辑,将真正的单元格的内容放置在tr
中,一个tr
管理它包含的那一行所有单元格元素,但实际上并不渲染tr
元素,如果设置tr { border: 1px red solid; }
,表格中每行并不会额外多一圈边框。tr
仅仅起管理的作用,自身并不存在。在视觉上似乎单元格是存在于tr
中的,基于tr
的存在而存在,但实际上这些单元格被渲染的原因并不是浏览器渲染tr
的子元素,而是浏览器渲染这些单元格自身而已。
而对于列元素col
和列群元素colgroup
,它也代表将要管理的列,浏览器不会渲染 真正的colgroup
和col
,但如果为colgroup
或col
设置样式,浏览器将会把这些样式应用在它所管理的列的元素上。
第一个colgroup
元素从第一列开始,往后囊括共其span
属性值(一个正整数,默认为能囊括之后的所有列的数字)的列数。后面的colgroup
则从前一个colgroup
元素囊括的后一列开始,继续向后囊括共其span
属性值的列。
作为colgroup
之内的col
元素,其更像是colgroup
colgroup
的span
值表示在该colgroup
内,从其囊括的第一个列开始,到共col
元素的span
(默认值为1)个列。即其所属的colgroup
的一个子集,实现对colgroup
的精准控制。
我们直接看示例:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title> col和colgroup元素示例</title>
<style type="text/css">
* {
color: red;
text-align: center;
}
div{
display: flex;
align-content: center;
justify-content: center;
}
table{
width: 80%;
}
table *{
border: green 1px solid;
}
table thead tr:first-child th:not(:first-child){
font-size: 30px;
font-weight: bold;
}
#date{
background: #dd05;
}
#imformation > col:first-child{
background: #0d05;
}
#imformation > col:nth-child(2){
background: #0005;
}
</style>
</head>
<body>
<div>
<table>
<colgroup span="2" id="date">
</colgroup>
<colgroup span="4" id="imformation">
<col span="1">
<col span="3">
</colgroup>
<caption>2021年借贷业务记录表</caption>
<thead>
<tr>
<th colspan="2">2021</th>
<th rowspan="2">号码</th>
<th rowspan="2" style="width: 30%;">摘要</th>
<th rowspan="2" style="width: 20%;">借方</th>
<th rowspan="2" style="width: 20%">贷方</th>
</tr>
<tr>
<th>月</th>
<th>日</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td>1</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>2</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>3</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>4</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>5</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
在这里我们明确几个细节
1.若一个元素跨越了多列或多行,其所在位置是其第一行第一列,在上述代码中,我们如果单独对第一列施加样式,一样能应用在左上角第一个单元格上。且不是值应用一半,是整个单元格全部被应用该样式。
2.不要尝试将colgroup
或col
的span
属性设计为超出总列数。我比较抵制这些边缘试探的行为,所以也不做讨论。
HTML表格就讨论到这里,谢谢阅读。
参考:
《HTML5权威指南》