标准化——表格

对于那些刚接触CSS布局的人来说,常对如何使用表格(table)感到迷惑。我在很多地方看到人们把“避免用表格来布局”理解成“完全不使用table标签”。值得注意的是,表格是可以用的而且非常好用——只要用的正确。

是的,你得尽量的去避免用表格来布局。但是对于表格型数据,你就应该使用table。我想谈谈如何使用表格来组织表现表格型数据。在HTML和XHTML里,表格不仅仅是行(row)和单元格(cell),还有很多其他元素,特别是如果你想让数据更加容易理解。

首先来点背景知识,“避免用表格来布局”这句话可以在HTML 4.01 规范表格介绍部分里面找到:

表格不应该纯粹的被用来布局文档内容,这样可能在处理渲染非可视媒体的时候产生问题。另外,当和图片一起使用的时候,这些表格可能在某个系统上显示过大而强迫用户拖动水平滚动条,为了减少这些问题,设计者应该使用样式表来控制布局而不是表格。

这样已经很明白了,尽管文档中说“应该”而不是“必须”,所以这个规范还是有弹性的。

但是本文并不是讨论是否使用表格布局,而是使用表格来组织表现表格型数据——这是表格诞生的本意。

当表格用来组织实际的数据时,不仅仅是一个编排布局的格子而已。一般人可以从表格的编排和表现上看出标题和数据单元格之间的关系。盲人或者有视觉障碍的人则不能做到这一点。如果一个表格要让那些使用屏幕阅读器或用其他非可视用户代理(UA)的人们能够理解,它则需要告诉用户代理它包含的信息之间是如何联系起来的。

幸运的是,HTML在这方面提供了很多元素和属性。然而,使用这些可以增强易用性和语义化的功能比较难而且本身不容易理解。在本文中,我尝试着解释如何使用他们。

表头, <th>

让我们从一个非常简单的表格开始——只包含一行表头和两行三列的数据。如果用以前流行的做法,只用表格的行和单元格,写出来就如下:

  1. <table>

  2. <tr>

  3. <td>公司</td>

  4. <td>雇员</td>

  5. <td>成立于</td>

  6. </tr>

  7. <tr>

  8. <td>ACME Inc</td>

  9. <td>1000</td>

  10. <td>1947</td>

  11. </tr>

  12. <tr>

  13. <td>XYZ Corp</td>

  14. <td>2000</td>

  15. <td>1973</td>

  16. </tr>
  17. </table>

没有边框和修饰,那么上面的代码在你现在的浏览器里看起来就如下:














公司 雇员 成立于
ACME Inc 1000 1947
XYZ Corp 2000 1973

用CSS稍微修饰一下表格,你可以使表头在图形化浏览器里面更加明显:

table.extbl{border-collapse: collapse;font-size:12px;}table.extbl td,table.extbl th{border: 1px solid black;padding: 4px;}table.extbl tr.headers{font-weight: bold;}














公司 雇员 成立于
ACME Inc 1000 1947
XYZ Corp 2000 1973

一个视力正常的人,很容易并且很快就可以明白表头和数据单元格之间的关系。从另一方面讲,那些使用屏幕阅读器的人可以听到如下顺序的词:公司,雇员,成立于,ACME Inc,1000,1947,XYZ Corp,2000,1973。不是十分容易明白其中的关系。

第一步——最简单的——通过适当的标出表头来使得表格更加有意义。很简单:只要使用<th>标签取代表头的<td>标签即可。

  1. <table>

  2. <tr>

  3. <th>公司</th>

  4. <th>雇员</th>

  5. <th>成立于</th>

  6. </tr>

  7. <tr>

  8. <td>ACME Inc</td>

  9. <td>1000</td>

  10. <td>1947</td>

  11. </tr>

  12. <tr>

  13. <td>XYZ Corp</td>

  14. <td>2000</td>

  15. <td>1973</td>

  16. </tr>
  17. </table>














公司 雇员 成立于
ACME Inc 1000 1947
XYZ Corp 2000 1973

这个例子虽然简单,但是已经包含了足够的信息使得屏幕阅读器能够让使用者明白表头和数据单元格之间的关系。一个屏幕阅读器一般会这么读:公司: ACME Inc. ,雇员: 1000,成立于: 1947., 以此类推。比之前好多了。

表格标题, <caption>

<caption>标签可以为表格提供一个简短的说明,和图像的说明比较类似。默认情况下,大部分可视化浏览器显示表格标题在表格的上方中央。CSS里的caption-side属性用来控制表格标题显示的地方。大部分浏览器只能把表格标题显示在表格的上方或者下方,只有一些浏览器支持左边或者右边。这个就留给大家去试试了。

使用的时候,<caption>标签一定要紧接着开始的<table>标签写,如下:

  1. <table>

  2. <caption>Table 1: Company data</caption>

  3. <tr>

  4. <th>Company</th>

  5. <th>Employees</th>

  6. <th>Founded</th>

  7. </tr>

  8. <tr>

  9. <td>ACME Inc</td>

  10. <td>1000</td>

  11. <td>1947</td>

  12. </tr>

  13. <tr>

  14. <td>XYZ Corp</td>

  15. <td>2000</td>

  16. <td>1973</td>

  17. </tr>
  18. </table>















Table 1: Company data
Company Employees Founded
ACME Inc 1000 1947
XYZ Corp 2000 1973

当然你也可以用CSS去样式化表格标题。然而,要在不同浏览器里获得同样的效果还需要一定的技巧,这个也留给各位去实践了。

表格释义:summary属性

一般人可以很容易的决定是否研究一下表格的细节,只要瞥一眼就可以看出表格有多大、大概有什么内容。但是使用屏幕阅读器的人就不是那么容易了,除非我们给表格加上summary属性。这样可以提供比<caption>标签更详细的描述。

sumary属性的内容不会被可视化浏览器显示,所以可以尽可能的让描述足够长,使得那些用“听”的浏览者了解表格的内容。当然也不要用过头了,当有需要的时候才加上summary属性,比如对于很复杂的表格,添加一个summary属性可以使用屏幕阅读器人比较简单的了解表格的内容。

  1. <table summary="The number of employees and the foundation year of some imaginary companies.">

  2. <caption>Table 1: Company data</caption>

  3. <tr>

  4. <th>Company</th>

  5. <th>Employees</th>

  6. <th>Founded</th>

  7. </tr>

  8. <tr>

  9. <td>ACME Inc</td>

  10. <td>1000</td>

  11. <td>1947</td>

  12. </tr>

  13. <tr>

  14. <td>XYZ Corp</td>

  15. <td>2000</td>

  16. <td>1973</td>

  17. </tr>
  18. </table>

缩写表头:abbr属性

当屏幕阅读器遇到一个表格,每一行会把表头连每一个数据单元格一起读出来。如果表头很长,听一遍一遍的读是十分乏味的。通过使用abbr属性,可以给那些长的表头提供简写形式,取代表头的内容。abbr属性是可选的,大部分情况表头还是(或许是应该)比较简短的。

稍微修改一下刚才的表格,让表头更长些,abbr属性就可以这样用:

  1. <table summary="The number of employees and the foundation year of some imaginary companies.">

  2. <caption>Table 1: Company data</caption>

  3. <tr>

  4. <th abbr="Company">Company Name</th>

  5. <th abbr="Employees">Number of Employees</th>

  6. <th abbr="Founded">Foundation Year</th>

  7. </tr>

  8. <tr>

  9. <td>ACME Inc</td>

  10. <td>1000</td>

  11. <td>1947</td>

  12. </tr>

  13. <tr>

  14. <td>XYZ Corp</td>

  15. <td>2000</td>

  16. <td>1973</td>

  17. </tr>
  18. </table>















Table 1: Company data
Company Name Number of Employees Foundation Year
ACME Inc 1000 1947
XYZ Corp 2000 1973

对于第一行数据,屏幕阅读器会读表头的全称,而从第二行开始即使用简称。

这样让数据表格适应布局是挺困难的,而以下的做法更为常见:即让表头尽可能的短,或者简写,使用title属性或者<abbr>标签提供一个更长的说明。

把表头和数据联系起来:scopeidheaders属性

就我用到现在,很多表格要比上面提供的例子复杂的多。让例子复杂一点,我会移去“Company”表头,并且把第一列的数据移到表头单元格里:

  1. <table summary="The number of employees and the foundation year of some imaginary companies.">

  2. <caption>Table 1: Company data</caption>

  3. <tr>

  4. <td></td>

  5. <th>Employees</th>

  6. <th>Founded</th>

  7. </tr>

  8. <tr>

  9. <th>ACME Inc</th>

  10. <td>1000</td>

  11. <td>1947</td>

  12. </tr>

  13. <tr>

  14. <th>XYZ Corp</th>

  15. <td>2000</td>

  16. <td>1973</td>

  17. </tr>
  18. </table>















Table 1: Company data
  Employees Founded
ACME Inc 1000 1947
XYZ Corp 2000 1973

在这个表格里,每一个数据单元格都有两个表头。最简单的方法让那些非可视的浏览器理解这个表格,就是为每个表头添加一个scope属性。

  1. <table summary="The number of employees and the foundation year of some imaginary companies.">

  2. <caption>Table 1: Company data</caption>

  3. <tr>

  4. <td></td>

  5. <th scope="col">Employees</th>

  6. <th scope="col">Founded</th>

  7. </tr>

  8. <tr>

  9. <th scope="row">ACME Inc</th>

  10. <td>1000</td>

  11. <td>1947</td>

  12. </tr>

  13. <tr>

  14. <th scope="row">XYZ Corp</th>

  15. <td>2000</td>

  16. <td>1973</td>

  17. </tr>
  18. </table>

Scope属性同时定义了行的表头和列的表头:

  • col: 列表头
  • row: 行表头

在第一行的 加上值为colscope属性,声明他们是下面数据单元格的表头。同样的,给每行的开头<th>加上值为rowscope属性声明他们是右边数据单元格的表头。

Scope属性还有两个值:

  • colgroup: 定义列组(column group)的表头信息
  • rowgroup: 定义行组(row group)的表头信息

一个列组是由<colgroup>标签定义的。行组则是由<thead><tfoot><tbody>定义的。稍后我将会详细介绍它们。

如果你既想要保留“Company”表头,而又想让公司名字作为行表头(row headers)显示,你会怎么做?那样的话,应该使得包含公司名字的单元格同时提供表头和数据信息。也就是说,<td>标签也应该加上scope属性:

  1. <table summary="The number of employees and the foundation year of some imaginary companies.">

  2. <caption>Table 1: Company data</caption>

  3. <tr>

  4. <th scope="col">Company</th>

  5. <th scope="col">Employees</th>

  6. <th scope="col">Founded</th>

  7. </tr>

  8. <tr>

  9. <td scope="row">ACME Inc</td>

  10. <td>1000</td>

  11. <td>1947</td>

  12. </tr>

  13. <tr>

  14. <td scope="row">XYZ Corp</td>

  15. <td>2000</td>

  16. <td>1973</td>

  17. </tr>
  18. </table>

这样的话可视化浏览器不会默认的把company name显示为表头。所以需要用CSS来修正一下,就刚才那个例子,我使用了下面的CSS:

  1. td[scope] {

  2. font-weight:bold;
  3. }

要注意上面的规则使用了属性选择符,IE是不支持的。而通过添加一个class来样式化表头是个不错的办法。















Table 1: Company data
Company Employees Founded
ACME Inc 1000 1947
XYZ Corp 2000 1973

另一个连接表格数据单元格和表头的方法就是给每一个表头添加一个唯一的ID。然后为下面的数据单元格添加headers属性,这个headers属性值包含用空格分开的各个ID,这些ID代表的表头各自关联到该数据单元格上。这样做很复杂,只是当有超过两个表头的单元格才用。在复杂的和不规则的表格中,scope属性就力不从心了。

为了演示,我修改了一下表格,加上了公司雇员性别及人数:

  1. <table class="extbl" summary="The number of employees and the foundation year of some imaginary companies.">

  2. <caption>Table 1: Company data</caption>

  3. <tr>

  4. <td rowspan="2"></td>

  5. <th id="employees" colspan="2">Employees</th>

  6. <th id="founded" rowspan="2">Founded</th>

  7. </tr>

  8. <tr>

  9. <th id="men">Men</th>

  10. <th id="women">Women</th>

  11. </tr>

  12. <tr>

  13. <th id="acme">ACME Inc</th>

  14. <td headers="acme employees men">700</td>

  15. <td headers="acme employees women">300</td>

  16. <td headers="acme founded">1947</td>

  17. </tr>

  18. <tr>

  19. <th id="xyz">XYZ Corp</th>

  20. <td headers="xyz employees men">1200</td>

  21. <td headers="xyz employees women">800</td>

  22. <td headers="xyz founded">1973</td>

  23. </tr>
  24. </table>




















Table 1: Company data
  Employees Founded
Men Women
ACME Inc 700 300 1947
XYZ Corp 1200 800 1973

你可以发现,这种方法真的很麻烦,所以如果可能的话,还是尽量用scope属性吧。

跨行和跨列

在以前用表格布局的年代,rowspan属性和colspan属性常被用来让单元格跨几列或跨几行,来布局那些经过整齐切割的图像。这两个属性现在还在用, 因为并没有CSS来控制单元格的跨行和跨列。仔细想想,其实是很有道理的:跨行和跨列示表格结构(structure)的一部分,而不是其表现(presentation)。

列和列组:<col><colgroup>

HTML提供了<colgroup><col>标签来为相关的表格列分组。这样就可以(在一些浏览器中)使用CSS来单独的为列样式化。列组也可以使用scope属性来标明其表头信息。

这就是我要说的关于列和列组的全部。更多信息参考“其他”部分。

行组: <thead>, <tfoot>, 和<tbody>

表格的行可以分组为表头组(<thead>), 表尾(或表注)组(<tfoot>), 然后是一个或多个表身(<tbody>) 。每一个行组必须包含一个或多个表格行。

如果一个表格包含<thead>,那么它必须出现在<tfoot><tbody>之前。而<tfoot>则必须出现在<tbody>之前。如果没有使用<thead><tfoot>,那么<tbody>标签也可以不加(也不是非得不加,随你喜欢了)。一个有行组的表格结构看起来如下:

  1. <table>

  2. <thead>

  3. <tr></tr>

  4. … 更多表头的行

  5. </thead>

  6. <tfoot>

  7. <tr></tr>

  8. … 更多表尾的行

  9. </tfoot>

  10. <tbody>

  11. <tr></tr>

  12. … 第一个<tbody>的行

  13. </tbody>

  14. <tbody>

  15. <tr></tr>

  16. … 第二个<tbody>的行

  17. </tbody>

  18. … 更多的<tbody>
  19. </table>

使用行组有以下几个原因:

  • 这样样式化表头、表尾和表身比较方便,而且独立,不必要给每个标签加样式或class。
  • 当打印比较长的表格的时候,一些浏览器(比如基于Mozilla的)会在每一页的开头重复表头和表尾的内容,这样阅读打印版本的表格就比较方便。
  • 区分开表头和表尾也可以使一些浏览器浏览表格的时候,只滚动表身。

仅为数据表格而写

本文所写的所有都是关于使用HTML表格来组织和表现数据。如果你还是想用表格来布局,那么上文所述的都没有意义而且用不到。没有summary属性、没有表头、没有<caption>、什么都没有,没有格式,陈旧的布局表格除了<table>,<tr>,<td>什么都可以不要。另外还要承担风险,即如何面对那些非可视的用户代理(UA)。

优势

看来要用HTML做一个有语义化的数据表格有很多工作。对于复杂的表格是这样的。有时候基本上是不可能手工写出来的。但是对于简单的表格,那么使用一个<th>加上scope属性就可以了,又快又简单。

非常明显,语义化的表格对于使用屏幕阅读器或其他辅助技术的浏览者非常有好处。让那些巨大而复杂的表格“听”起来很有意义是非常困难的,所以尽可能的使表格简单。

另外对于使用可视化浏览器的设计者和用户也是有好处的:一个语义化的表格有大量的接口可以利用CSS来样式化,好的样式可以让表格更加易用。

其他

除了本文,还有更多关于数据表格内容。比如这里就没有提到axis属性,并且对于<colgroup><col>的描述也不是很深。对于格式化和样式化还有border模型我也没有深究,还缺少一个真正复杂的表格的例子。

想了解更多信息,可以参考以下文章:

(0)

相关推荐

  • 标准化——表格

    对于那些刚接触CSS布局的人来说,常对如何使用表格(table)感到迷惑.我在很多地方看到人们把"避免用表格来布局"理解成"完全不使用table标签".值得注意的是,表格是可以用的而且非常好用--只要用的正确. 是的,你得尽量的去避免用表格来布局.但是对于表格型数据,你就应该使用table.我想谈谈如何使用表格来组织表现表格型数据.在HTML和XHTML里,表格不仅仅是行(row)和单元格(cell),还有很多其他元素,特别是如果你想让数据更加容易理解. 首先来点背

  • 创建无表格网站的原因和原则 译文

    In a time of web developers who just like to say that 'Tables are Evil' and can't (or won't) explain why, this article will attempt to give you some solid reasons that people create tableless designs. Included are six major benefits of creating table

  • 使用python对excel表格处理的一些小功能

    python对excel表格处理的一些小功能 功能概览pandas库的一些应用文件读入计算表格中每一行的英文单词数简单用textblob进行自然语言情感分析判断一行中是不是有两列值都与其他行重复(可推广至多列)对表格中的两列自定义函数运算判断表格中某列中是否有空对表格某列中时间格式的修正运用matplotlib画时间序列图,重叠图 功能概览 做数模模拟赛时学到的一些对表格处理的知识,为了方便自己以后查找,遂写成一篇文章,也希望能帮助大家:) pandas库的一些应用 文件读入 代码如下,每一句后

  • Flex中对表格某列的值进行数字格式化并求百分比添加%

    1.问题背景 一般的,需要对表格中某列的数值进行格式化,对该数值乘以100,并保留两位小数,添加"%" 2.实现实例 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"

  • Flex中对表格中某列的值进行数字格式化保留两位小数

    1.问题背景 一般的,表格中展示的比率,对比率的处理是:保留两位小数,并向上保留 2.实现实例 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="libr

  • Flex中怎么给表格中的滚动条定位避免刷新回到原处

    1.问题背景 如果表格中的字段过多,会出现滚动条,在将滚动条滚到一定的位置时,重新刷新表格,滚动条会回到原处,原来查看的字段还得继续滚动,才能查看到. 2.实现实例 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/f

  • 锁定行头和列头的表格组件

    1.在页面中引入风格单定义 <style> .LockHeadTable {behavior:url(/oblog312/LockHeadTable.htc)} </style> 2.在需要锁定行列头的表格定义中添加语句"class="LockHeadTable""就OK了,其他参数有 ROWHEADNUM="锁定行数" COLHEADNUM="锁定列数" ROWHEADSTYLE="行表头风

  • Web上功能强大的DbGrid表格HTC组件[只需在Table中指定样式就可以完成多种功能可扩展]

    Grid.htm 复制代码 代码如下: <style> INPUT { DefineINPUTOnClick:expression(this.onclick=function(){if(this.type=="button"){this.style.color=chooseColor();}}); } </style> <script> var iGridRowCount=0; var iGridColCount=0; function create

  • 动态表格Table类的实现

    复制代码 代码如下: /// <reference path="Lib.js" /> /// <reference path="DabaBinder.js" /> //引入DataBinder.js include("DataBinder.js"); /* <table border="1"> <thead><tr> <th></th> <

  • AngularJS模糊查询功能实现代码(过滤内容下拉菜单排序过滤敏感字符验证判断后添加表格信息)

    注:添加球员的功能无指定技术要求,添加球员的页面也无具体样式要求. 1.实现上图页面所有元素,页面布局规整,跟上图效果一致 2.实现文案显示,按效果显示 3.实现查询,实现查询敏感词过滤,实现查询后列表变化 4.实现倒序,实现正序,下拉列表排序效果都实现 5.按钮背景一致,按钮样式 6.实现添加球员页面,添加球员页面样式,添加球员功能,添加球员必填项判断,添加完球员后能显示在表格内,已存在球员判重. 7.表格样式跟上图样式一致 代码: <!DOCTYPE html> <html lang

随机推荐