33. 样式表格
- 详细资料
- 发布于 2012年9月18日
- 点击数:4533
序言
在目前的web开发中,表格有时候似乎有点儿被误解了。人们非常在意“不要使用表格!”,但往往忘记了这句话其实是在说“不要用表格来进行布局”。表格在其真正用途——显示表状数据方面是非常卓越的。所以,了解如何妥善地对其进行样式化是很有意义的。
本教程侧重于如何高效地应用CSS来创建明晰易读的数据表风格。本文也会涉及到一些常见的表格设计要求。本文结构如下:
下载本文中表格的代码示例可能会对你有所帮助,这样你就可以跟着本文的进度来练习了。
表格结构
在我们开始钻研CSS之前,先来了解一下创建明晰的样式所需的表格关键结构元素。
- 表格的表头
- 表格数据单元
- 表格标题
当网站用户浏览你的表格时,应该让他们能轻松看懂表格的结构。为了达到这个目的,最常见的办法是使用边框或背景颜色,或者二者兼用。
你并不是非得遵守这些样式惯例,但你应当确保th
和td
单元格之间有明显的差别;同样,caption
应当与表格明显相关,并与页面上的其它文本有显著的差别。
基本原理
看看下面这个未经样式处理的表格是如何提供信息的(下面这个例子跟你在第19篇——HTML 表格中看到的那个例子是一样的):
Volcano Name | Location | Last Major Eruption | Type of Eruption |
---|---|---|---|
Compiled in 2008 by Ms Jen | |||
Mt. Lassen | California | 1914-17 | Explosive Eruption |
Mt. Hood | Oregon | 1790s | Pyroclastic flows and Mudflows |
Mt. St. Helens | Washington | 1980 | Explosive Eruption |
这张表格读是能读懂,但是得花点儿功夫才能弄明白到底在讲什么。下面我们给它加上一些样式来使它更易读。
表格和单元格宽度
首先我们要决定表格的宽度。浏览器的默认值等价于这个设置:table { width: auto; }
,这会使表格宽度随内容的宽度而改变。一般来说,这样的效果会显得比较凌乱。
假设我们的表格处在一个宽600px的内容栏中。为了充分利用空间,我们将表格宽度设置为可用宽度的100%.由于表格有四列,我们将每个表格单元的宽度都设为25%:
table { width: 100%; } th, td { width: 25%; }
实际上你可以仅在th
上设置宽度,该值会设定所有列的宽度;但是这种做法并不是很严密。这个简单的样式的效果如图1所示:
图1:简单设置了宽度的示例表。
现在单元格都是等宽的。稍后我们会做不等宽的单元格,不过现在我们还是继续向前推进。
文本对齐
现在表格还是有点难以阅读,为了让它整洁一点儿,我们来设置一下文本对齐——下面添加的代码可以使表头左对齐,以便与其下方的内容相匹配(默认状态下,浏览器会使表头居中对齐):
table { width: 100%; } th, td { width: 25%; text-align: left; }
现在表格要整洁一点了,如图2所示:
图2:应用左对齐后的表格。
现在所有单元格都是垂直居中对齐的了。如果你愿意的话,可以将文本对齐到单元格顶部或底部,或任何你喜欢的vertical-align
设置。下面新添加的代码是将文本对齐到顶部:
table { width: 100%; } th, td { width: 25%; text-align: left; vertical-align: top; }
现在的表格外观如图3所示:
图3:添加了垂直对齐的表格。
注意,所有的表头都处在单元格顶部,即便是占了两行的"Last Major Eruption"也是如此。
边框
这张表现在看齐来要美观一点了,但逐行阅读还是有点困难。是该设置一下边框来让表格更易读了。你需要为表格的每个部分设置边框,然后再来看各个边框该怎样合并。
为了说明边框的位置,图4标出了各种不同的边框:table
(solid black
), caption
(solid grey
), th
(dashed blue
)和td
(dotted red
):
图4:表格内各种不同元素的边框演示。
注意,table
边框环绕在所有表头和数据单元格外面,并位于单元格和标题之间。th
和td
彼此之间留有间距,你也可以在默认状态下看到这种效果。
来看看另一种样式的表格——你可以用border
属性为表格和单元格创建简单的黑色边框——可通过下面的新增代码来实现:
table { width: 100%; border: 1px solid #000; } th, td { width: 25%; text-align: left; vertical-align: top; border: 1px solid #000; }
效果如图4:
图4:带简单黑色边框的表格。
这样,每一行就好读多了,但你也许不会喜欢单元格之间的间隙。有两种方法可以改变这种外观。
第一,你可以直接用border-spacing
属性来弥合间距,就像这样:
table { width: 100%; border: 1px solid #000; } th, td { width: 25%; text-align: left; vertical-align: top; border: 1px solid #000; border-spacing: 0; }
这样边框就会彼此相接,而不是相离。它将1px宽的边框变成了2px宽,如图5所示:
图5:无边框间距的表格,具有2px边框效果。
你也可以用border-spacing
属性来增加单元格间距,但要记住这项属性在IE中不起作用。
如果你想保留1px边框效果,就得设置表格,使边框彼此“合并”。可用border-collapse
属性来代替border-spacing
属性以达到这种效果:
table { width: 100%; border: 1px solid #000; } th, td { width: 25%; text-align: left; vertical-align: top; border: 1px solid #000; border-collapse: collapse; }
这样就会产生图6所示的只有1px边框的表格了:
图6:用border-collapse设置来合并边框,将边框宽度减为1px的表格。
当你设置边框合并时,你得记住如果邻近的单元格的边框样式不同的话,就会产生问题。不同的边框样式彼此合并的时候,它们会互相“冲突”。在W3C CSS2 表格边框冲突解决法则中这个问题得到了解决,该法则规定了在合并时,哪一种样式会“赢”。
填充距
现在单元格已经加上了边框,你可能会想为标题和单元格加一些空白。直接用填充距就可以达到这种效果:
table { width: 100%; border: 1px solid #000; } th, td { width: 25%; text-align: left; vertical-align: top; border: 1px solid #000; border-collapse: collapse; padding: 0.3em; } caption { padding: 0.3em; }
这样就可以让文本稍微得到一点儿“放松”了,如图7所示:
图7:给各单元格加上填充距后的表格。
标题摆放
到目前为止,表格标题都还是位于表格顶部。不过你可能会想把标题移到别的地方去。可惜在IE中没法实现这个,但是在其它浏览器下你都可以用caption-side
属性来改变标题的位置。该属性的选项有顶部,底部,左侧和右侧。下面我们来把标题移到底部:
table { width: 100%; border: 1px solid #000; } th, td { width: 25%; text-align: left; vertical-align: top; border: 1px solid #000; border-collapse: collapse; padding: 0.3em; caption-side: bottom; } caption { padding: 0.3em; }
效果如图8。
图8:标题位于底部的表格。
如果你想移动标题的话,要牢记任何side-specific样式在IE下都无法奏效。比如,即使你加了三条边框来使标题与表格底部连接,在IE下也不会有效果,标题仍然会位于表格顶部。你只有用条件注释来在IE下改变你的表格式样。更多详细内容将会在稍后的利用条件样式来满足IE的要求部分谈到。
至于其它的示例,我在开头已经给出了。
背景
另一种样式化表格的简单方法是添加背景颜色和图片。这是通过background
属性来完成的,但你要注意的是,表格的各个部分会“一层叠一层”。CSS2 规范说明了背景层次的一些细节,简短地说就是背景会以下面的顺序彼此重叠:
- 表格(位于“底部”或“后部”)
- 列组
- 列
- 行组
- 行
- 单元格(位于“顶部”或“前部”,也就是说单元格的背景覆盖在所有其它背景之上)
因此,如果你为表格设置了一个背景,而为单元格设置了另一个背景颜色的话,单元格的背景将会覆盖表格的背景。如果你的边框设置为collapse
,就根本看不见表格的背景了。然而,如果你将border-collapse
设为separate
的话,表格背景将显示在单元格间隙之中。
注意,网页中不同元素互相覆盖的情况是可调节的;通过改变某个元素的z-index
属性,你可以控制该元素在“堆”中相对于其它元素的位置。在第37篇文章中你可以学到更多关于z-i ndex的知识。
假设你将表格背景设为红色,单元格背景设为白色。不相连的单元格可以露出红色来,但单元格本身仍然是白色的,如图9所示:
图9:单元格的白色背景之间露出红色的表格背景。
你也可以使用背景图片。比如,假如你想在单元格之间显出渐变,你可以将th
和td
单元格设为白色背景,将table
背景设为一张渐变图片:
table { border-collapse: separate; border-spacing: 5px; background: #000 url("gradient.gif") bottom left repeat-x; color: #fff; } td, th { background: #fff; color: #000; }
注意,背景颜色是设为黑色的,用以充满渐变图片结束后在表格顶部留下的空白(你应当使表格总比背景图片长一点)。前景色设为白色,以免默认颜色在单元格内容上显露出来。一般来说,单元格样式会覆盖table {}
样式所设置的文本颜色,但是你还是应当声明每一层的前景和背景对比色。
在大多数浏览器下,上述样式的效果如图10所示:
图10:渐变背景图像在单元格之间的显示
由于IE不支持border-spacing
,在默认状态下它是不能显示同样的背景效果的。但你仍可以得到大致差不多的效果,如图11所示:
.图11:IE渲染出来的border-spacing间距变小了
随着情况的不同,你可能会很乐意就这么接受浏览器之间的渲染效果差异。当然这并非总是可行,比如某个客户可能会特别要求你的设计在所有浏览器下外观完全一致。
利用条件样式来适应IE
有一个变通方案可以解决上述的IE问题。尽管这需要一点技巧以及一张附加样式表,但它相当有效。你可以用expression
来生成更宽的间距,然后用条件注释来载入该表达式。该表达式语法为:
table {
border-collapse: expression("separate", cellSpacing = "5px");
}
这段CSS仅对IE有效,因此你只能将其用在IE上。这个表达式还会使你的样式表失效,所以许多开发员宁愿单独用一张只在IE上加载的样式表来书写IE伎俩。
为了达到这个目的,我们新建一张样式表,命名为ie-only.css,并将其链接在条件注释中。
<!--[if lte IE 7]><link rel="stylesheet" media="screen" href="/ie-only.css" /><![endif]-->
注意[if lte IE 7]
的意思是“如果浏览器版本低于或等于IE7”。该语句将这段代码应用于IE7及更早的IE版本上,而周围的HTML注释将这段代码对其它所有浏览器隐藏。你可以将该语句调整为针对IE的任何其它版本,比如你想指向IE6的话,就用[if IE 6]
。
在主样式表中设置普通样式:
table {
border: 1px solid #000;
border-collapse: separate;
border-spacing: 5px;
background: #000 url("gradient.gif") bottom left repeat-x;
}
然后在ie-only.css
中设置仅针对IE的样式:
table { border-collapse: expression("separate", cellSpacing = "5px"); }
这样IE就会生成宽单元格间距的表格。别忘了对你的特殊宽度设置进行维护——如果你更新了主样式表的话,也必须要更新ie-only.css
才行。显然,比起单单样式化表格来说,条件注释使你能做出更多的效果,因为附加样式表足以容纳适应IE漏洞所需的所有CSS。
一个简单的设计
大多数网页设计使用的都是相对简单的背景组合。现在我们来将表头背景设置为灰色,将标题改成黑底白字:
table { width: 100%; border: 1px solid #000; } th, td { width: 25%; text-align: left; vertical-align: top; border: 1px solid #000; border-collapse: collapse; padding: 0.3em; caption-side: bottom; } caption { padding: 0.3em; color: #fff; background: #000; } th { background: #eee; }
效果如图12所示:
图12:将标题颜色反向成黑底白字,表头单元格背景改成浅灰色的表格
常见的变化
在这一部分中我们将会看到一些常见的设计原型,这些设计在网页表格上总是一再地出现。
斑马纹
有种常见的表格设计要求是使表格行的颜色产生交替。这种颜色交替通常被称作“斑马纹”。虽然对于斑马纹是否真的有助于阅读存在一些猜测,但它们的确是一种流行的样式。斑马纹示例如图13所示:
图13: 一张“斑马纹”表格,表格行设置为白色与灰色交替。
实现斑马纹效果最简单的办法是添加一个类来使表格行产生交替,然后用CSS上下文选择符来样式化行中的单元格。首先,将“odd”类和“even”类添加到表格行中,就像这样:
... <tr class="odd"> ... <tr class="even"> ...
由于表头已经有自己的样式了,你可以将其跳过不管。然后添加上下文类来设置odd类表格行中所有的单元格背景。
.odd th, .odd td { background: #eee; }
这是为跨浏览器的HTML表格添加条纹的最简单的办法,但是该方法并不是很完美——要是你在表格中插入了行的话又该怎么办呢?那你就得互换所有的odd
和even
类名来使一切重新搞定。
还有另外两种办法:
-
就如在A List Apart: 多条纹表格中所阐述的那样,你可以用非干扰性的JavaScript语言来添加类。 大多数JavaScript框架也有适用于多条纹表格的方法:多条纹表格之一决胜负中就将一系列框架的实现进行了比较。
-
你可以用CSS3
:nthchild
选择符,但该方法尚未获得所有主流浏览器的支持。不过随着时间的推移,浏览器支持也会得到改善。
不完全网格
S有的网页设计对于结构化程度较低、外观较开放的网格响应速度很快。对此,最简单的一种变化就是删除竖边框并省略标题栏的背景,如图14所示:
图14:仅在外缘和单元格底部有浅灰色边框的表格
实现该效果的CSS代码如下:
table { width: 100%; border: 1px solid #999; text-align: left; border-collapse: collapse; margin: 0 0 1em 0; caption-side: top; } caption, td, th { padding: 0.3em; } th, td { border-bottom: 1px solid #999; width: 25%; } caption { font-weight: bold; font-style: italic; }
在此之上你可以更进一步,删掉所有边框,只留下表格顶部和底部的边框以画出表格主体的界线——参见图15:
图15:仅在主体的顶部和底部有边框的表格。
实现该效果的CSS如下:
table { width: 100%; text-align: left; border-collapse: collapse; margin: 0 0 1em 0; caption-side: top; } caption, td, th { padding: 0.3em; } tbody { border-top: 1px solid #000; border-bottom: 1px solid #000; } tbody th, tfoot th { border: 0; } th.name { width: 25%; } th.location { width: 20%; } th.lasteruption { width: 30%; } th.eruptiontype { width: 25%; } tfoot { text-align: center; color: #555; font-size: 0.8em; }
内部网格
有时你可能会想删除表格的外边框,只保留由内部边框组成的网格,如图16:
图16:内部网格式的表格
为了在现行的所有浏览器上实现该效果,你需要为每行的最后一个th
和td
单元格添加一个类:
... <tr> <th scope="col">Volcano Name</th> <th scope="col">Location</th> <th scope="col">Last Major Eruption</th> <th scope="col" class="last">Type of Eruption</th> </tr> ...
然后我们用该类来删除这些单元格的右边框,完整的CSS如下:
table { width: 100%; text-align: left; border-collapse: collapse; margin: 0 0 1em 0; caption-side: top; } caption, td, th { padding: 0.3em; } th, td { border-bottom: 1px solid #000; border-right: 1px solid #000; } th.last, td.last { border-right: 0; } tfoot th, tfoot td { border-bottom: 0; text-align: center; } th { width: 25%; }
使用:lastchild
的内部网格
如果浏览器支持改善的话,我们就可以不用类,而用:lastchild
这个伪选择符来达到这种效果了。其CSS如下:
table { width: 100%; text-align: left; border-collapse: collapse; margin: 0 0 1em 0; caption-side: top; } caption, td, th { padding: 0.3em; } th, td { border-bottom: 1px solid #000; border-right: 1px solid #000; } th:lastchild, td:lastchild { border-right: 0; } th { width: 25%; }
目前这段代码只能在最新版的Opera, Firefox 和 Safari浏览器下工作。
两个常见的漏洞
在本文最后,我们来看两个十分常见的漏洞,这样当它们突然冒出来的时候你好有个准备。这两个漏洞与表格的边框和标题有关。
边框合并漏洞
当你将表格设置为border-collapse: collapse;
时,你将会发现在Firefox和Safari浏览器中表格特征的宽度显示有误。例如,你将表格、单元格和标题的边框都设为1px,Firefox将会在标题的左侧少渲染1px,如图17所示:
图17: border-collapse
漏洞影响了Firefox和Safari浏览器。
Safari浏览器也有同样的问题,只不过是在右侧。这个漏洞是由舍入问题引起的,归根结底就是如何显示“0.5像素”的问题。可能有人会争论说从本质上来讲这并不是漏洞,但由于浏览器不兼容,所以这事实上就是漏洞。
那么,有什么解决办法呢?如果你想同时使用1px的边框和标题背景,那就只有“忍”了。毕竟这只是一点小小的差别,而且不是什么致命的问题——也就是说,表格还是完全可以用的。所以许多人选择了接受浏览器之间的差异。就让网络顺其自然吧。
如果你愿意用宽一点的边框,比如2px,你可以直接给表格、单元格和标题设置1px的边框;然后将表格边框设为separate,并将它们的间距设为零:
table { border-collapse: separate; border-spacing: 0; border: 1px solid #000; } th, td, caption { border: 1px solid #000; }
至少在Firefox下,1px的边框能凑成我们想要的2px边框效果,避免了舍入问题的发生。但在Safari下还是会有点缺陷。
或者,你可以通过去掉标题的边框和背景颜色来隐藏这个问题。问题仍旧存在,只是你看不见罢了。这可能是最简单也最有效的解决办法了。
边距/标题漏洞
如果你使用了标题并在table
中设置了边距,要注意,Firefox和Safari可能会将表格边距放在单元格和标题之间。
为了在Firefox中消除这种现象,你可以设置table
的三个侧面的边距,显式设置caption-side
,然后在caption
中加入第四个边距。不幸的是,这种办法会激活Safari中的漏洞。所以,这其实算不上真正的解决办法,除非你愿意忍受Firefox或Safari二者之一的漏洞。
唯一可以同时避免Firefox和 Safari漏洞的办法是在标题侧设置零边距。例如,如果你的标题是位于表格顶部的话,你可以只设置右边距,底边距和左边距;或只设置底边距。如果所有内容元素都只设置了同一侧的边距的话,这个办法也能奏效,所以你并非必须设置边距来将邻近的内容与表格隔开。
总结
现在你应该已经充分掌握了表格的基本样式化选项。虽然浏览器的不协调导致了一些限制,但一般说来你还是应该能够毫不费力地创建清晰易读的表格了。还有要注意一下你的边框,给文本留点喘息的空间,并要注意背景的处理。
练习题
- 如何调节表格和单元格边框之间的间距?
- 当
table
的背景是一个颜色,th
和td
单元格的背景是另一个颜色,而border-collapse
设置为collapse
的时候,会发生什么? - 如何将不同的列设置为不同的宽度?
延伸阅读
- W3C: CSS2 Tables, with particular reference to the CSS2 table background layering section.
- A List Apart: A Dao of Web Design—"let the web be the web". A timeless article which will explain why a 1px difference between browsers doesn’t truly matter.
- A List Apart: Zebra Tables and A List Apart: Zebra Striping: Does it Really Help?
- Zebra striping tables with CSS3
- Supporting IE with conditional comments
- A CSS styled table | Veerle's blog & A CSS styled calendar | Veerle's blog
- Data Tables and Cascading Style Sheets Gallery shows off a variety of table designs (although be aware many do not meet W3C colour contrast recommendations).