没有单一的解决方案可以使任何<table>
都恰当地响应式。这就是我喜欢 Davide Rizzo 的这篇文章的原因:它承认这一点,然后继续提供一些解决方案。这是对我们已经探索了一段时间的领域 的补充。
内容和对比表格
网站上有许多类型的表格,其中内容可能与用于使其响应式的方法一样千差万别。我发现最令人沮丧的表格是对比表格或普通内容布局表格,实际上没有全面的基于 CSS 的解决方案来使这些类型的表格响应式。
我着手寻找一个灵活且简单的解决方案,无论内容是什么,它都可以用作可重用的 Web 组件。

表格标记对我们仍然有效吗?
标准表格标记似乎在语义上是有意义的,并且在对齐单元格方面做得相当不错。我的主要担忧之一是可访问性。当然,原生表格标记可以帮助使用屏幕阅读器的用户理解内容的阅读和导航顺序?
我使用一个简单的 最佳实践表格 进行了一些测试。使用一些屏幕阅读器(Chrome Vox 和 VoiceOver),我尝试导航标记
- ChromeVox 会告诉你你位于一个表格上,而 VoiceOver 还会告诉你表格有多少列和行(这很有用)。
- ChromeVox 和 VoiceOver 都不会告诉你何时位于表格标题上。
<thead>
、<th>
甚至scope="row|col"
似乎都没有任何作用!唯一识别标题的方法是将其包装在<h#>
标记中。 - 阅读器通过行浏览表格,无论您的内容如何排列。VoiceOver 至少允许您使用方向键向任何方向导航,但您仍然无法指示您应该按什么顺序导航。
本质上,标记中的任何内容都不会告诉屏幕阅读器用户内容是否应按行或列读取。最有意义的标记仍然来自非表格语义内容。
响应式表格的方法
让我们考虑一下表格可以如何以响应式方式运行的不同方式
- 压缩:如果列的内容很少,它们可能在移动屏幕上水平压缩而没有任何问题,因此不更改布局需要成为一个有效的选项。
- 垂直滚动:如果布局和内容是精确且关键的,用户可以向左或向右滚动。这在 CSS 中使用
overflow="auto"
包装器非常简单。 - 按行折叠:在小屏幕上将每一行拆分为自己的单列迷你表格。将
display:table
切换为display:block
将使用普通表格标记导致这种情况。 - 按列折叠:事情变得棘手的地方在这里。您不能使用纯 CSS 中的普通表格标记执行此操作,因为代码顺序按行排列,并且
<tr>
包装器将其锁定。我们要么必须更改标记,要么开始使用 JavaScript 进行操作。

不建议构建响应式表格的方式
通过反复试验,我放弃了这些方法
- 通过 JavaScript 生成第二个较窄的表格,并根据断点交替隐藏/显示。
原因?内容重复,不比“.m”网站好。将破坏表格内的任何唯一 ID。对于样式指南驱动的组件来说,这是一个糟糕的想法。 - 使用普通表格标记和 JavaScript 在断点处将表格重新排列成响应式版本。
原因?需要针对垂直和水平表格使用不同的标记。将破坏表格内容的任何 JS 初始化。需要大量的 JS 事件侦听器和 DOM 操作。 - 保留表格标记,但切换到
display:flex
以垂直对齐表格内容。
原因?无法使用<tr>
类型包装器跨行对齐单元格,并且display: table-cell
会覆盖flex-item
。
使用 Flexbox 实现响应式表格
1a) 针对面向行的表格…
- 按照移动设备或屏幕阅读器应该读取的顺序排列标记,使用语义标题和内容。
- 放弃所有“行”包装器的概念。
- 根据列或行的数量将每个单元格的宽度设置为百分比。
无法自动调整列宽。
查看 CSS-Tricks 的 Pen 响应式表格(按行) (@css-tricks) on CodePen。
1b) 针对面向列的表格…
- 按行设置 flex
order
以立即创建垂直表格。这必须是内联的,否则我们需要为每一行使用一个唯一的类。手动执行起来相当容易,或者 CMS 或 JavaScript 应用起来非常容易。
查看 CSS-Tricks 的 Pen 响应式表格(按列) (@css-tricks) on CodePen。
2) 样式以帮助建立连接
- 根据需要以任何模式单独设置单元格样式。
- 使用负边距修复单元格边框重复。
查看 Davide Rizzo 的 Pen 响应式表格(单元格样式) (@davidelrizzo) on CodePen。
3) 在小屏幕上折叠为块
在小屏幕媒体查询中,将所有内容设置为 display: block
。这给了我们响应式表格!
查看 CSS-Tricks 的 Pen 响应式表格(折叠) (@css-tricks) on CodePen。
3b) 折叠为选项卡或手风琴
- 选项卡和手风琴标记位于表格中的逻辑位置
- 根据单元格
order
切换行或列 - 使用
display: none
为视觉用户和屏幕阅读器切换
查看 CSS-Tricks 的 Pen 响应式表格(选项卡和手风琴) (@css-tricks) on CodePen。
其他增强功能




限制:无法在弹性表格上进行行跨度。
您可以对其他类型的标记使用相同的单元格样式
甚至标准表格标记!
查看 CSS-Tricks 的 Pen 响应式表格(备用标记)(@css-tricks)在 CodePen 上。
无 Flexbox 的回退方案
IE9 及以下版本不支持 Flexbox。对于旧版浏览器,您可以使用(Modernizer)检测 Flexbox 并显示移动版本,这是一个很好的优雅降级示例。
.no-flexbox .Rtable > .Rtable-cell {
display: block;
}
结论
总的来说,这种方法提供了极大的灵活性,您可以考虑使用这些技术替换所有内容表格。您可以轻松地继续添加不同的主题和样式,并且如果设计人员预先了解响应式表格的功能,他们会更加有效。
其他响应式表格资源
- 在 CSS-Tricks 上:响应式数据表格综述
- David Bushell:仅 CSS 的响应式表格
- Filament Group:Tablesaw(一组用于响应式表格的插件。)
- Jason Grigsby:选择响应式表格解决方案
- 在 CSS-Tricks 上:响应式数据表格
- Cody House:一个(响应式)产品对比表
这篇文章最初发表在 CodePen 上。
不错的文章。不过有一点值得注意的是,在 1b) 对于面向列的表格… 中,您指出您必须使用内联样式才能在每列上实现正确的顺序样式,但您应该使用
nht-child
这样来做继续努力 =)
这太难以维护了。你无法一眼看出它做了什么。
我完全可以一眼看出它做了什么。
那是我首先尝试的策略。挑战在于,您需要为每种可能的行数提供一行 CSS。如果您事先不知道最大行数(例如在组件库中),那么您何时停止呢?
我正在开发一个网站,该网站包含大量技术数据,并且有数千个硬编码的宽 HTML 表格。我使用的解决方案是第一个不推荐的解决方案“通过 JavaScript 生成第二个较窄的表格,并通过断点交替隐藏/显示”。我对这个解决方案并不完全满意,但它似乎比使用 x 滚动更佳。似乎每个更好的解决方案都需要更改标记。
我仍然认为表格应该是表格——我们不仅出于语音朗读的原因使用表格,还因为内容在语义上就是表格数据。表格在响应式方面是否很难处理?是的,但这并不意味着我们应该避免使用它们。
我希望在评论中找到其他人也持有这种观点。我仍然认为这里语义是有价值的。是的,屏幕阅读器在解释表格方面做得不好很糟糕。但这不会改变表格数据的本质。
没错。如果屏幕阅读器无法很好地阅读表格,那就由它们来修复。
我管理着一个网站,其中包含大量人们用来工作的表格数据。
我无法想象将所有内容更改为非表格内容并删除他们将其复制粘贴到 Excel 电子表格中的能力。这也是无障碍性。
同意,在理想情况下,我认为对于内容量少的表格,这种方法很好,在这些表格中,灵活性与响应式行为比语义更重要。
我非常努力地尝试保留语义,使用
<table><td>
而不是<div><div>
,您可以强制表格display:flex
,但<td>
本身就是display:table-cell
,它会覆盖子元素的“flex-item”行为。display:flex-item
不存在,可能是规范中的遗漏?一些小的想法
只有解决方案 #3 在我的 DT2(Marshmallow,最新版 Chrome)上可读。其他解决方案的边距/填充足够大,以至于单词溢出
关于表格的无障碍性
Voiceover 的支持比上面提到的更多。请参阅 http://webaim.org/articles/voiceover/#tables
此外,NVDA 和 Jaws(使用率明显更高)可以很好地读取 TH。
尽管如此,您仍然可以在不影响无障碍性的情况下继续使用您的方法,方法是添加 ARIA 角色(网格、行、列标题、网格单元格等)。
关于 js 技术,这是我的 2 美分:对于小屏幕,我将表格内容的一个轴提取到一个或多个选择元素中。这有点类似于选项卡选项……
前几天刚发现这个。 http://dbushell.com/2016/03/04/css-only-responsive-tables/ 我喜欢它用于响应式表格。不过,我不确定它的无障碍性如何。顺便说一句,在“最佳实践表格”中,图例不应该是标题吗?此外,
tfoot
不应该放在tbody
之前吗?还是这些是故意设计的?非常棒的解决方案!感谢此链接
这是一个非常好的垂直滚动响应式表格实现。
感谢您对“最佳实践表格”笔的更正,已修复!
图例确实应该是标题。图例是表单标记,标题是表格标记。“最佳实践表格”示例不是有效的 HTML;此时不允许使用图例,它应该位于
fieldset
内部。tfoot
可以放在tbody
之前或之后。它们的顺序无关紧要。CodePen 的示例中仍然显示了一个图例元素。实际表格没问题,但在
<pre><code>
示例中仍然显示了图例。我想知道是否屏幕阅读器的选择错误地影响了设计方向。这两款(只有2款?)屏幕阅读器是否真正代表了将使用该内容的社区?或者它们是最“功能有限”的,因此我们需要简化内容以覆盖一些长尾用户?这些设计理念在 Jaws、WindowEyes 和 NVDA 等更流行的屏幕阅读器下如何工作?
我想你也可以轻松地反过来做——如果你采用移动优先的方式。
对于移动浏览器/小屏幕和旧版 IE,默认使用
display:block
,对于大屏幕/当前 IE,通过媒体查询使用flexbox
。因此,渐进增强,优雅降级。并且额外的好处是它不需要 JS 甚至像 Modernizr 这样的(可能额外的)库。
抱歉,这两个词不见了。/ 下划线是为了突出插入内容,而不是为了传达强调 :)
这是一篇很棒的文章。有一点它没有真正考虑的是表头和表尾。如果只是一个数据表,这很好用,但我喜欢用 JavaScript 在每个表格数据单元格上放置一个变量,该变量基于表头列,然后使用 CSS 在移动设备上显示它。例如,
data-label="Header Title: "
,然后在移动设备上添加.td:before{content:" "attr(data-label);}
我觉得使用
overflow: auto
的包装器仍然是最好的方法,原因有很多。表格布局得以保留……因此数据仍然有意义。
不需要任何额外的工作(避免额外的错误)
主要缺点是您并不总是注意到水平滚动条,或者只有在滚动到(长)表格底部时才会注意到。
好文章!我认为堆叠列并将每一行变成一大块是可行的方案。我编写了一个 jQuery 插件来实现这一点:https://github.com/michaelsoriano/stacked-rows
基本上它在每一行下面创建隐藏的 div——只在特定的媒体查询中显示。
关于屏幕阅读器如何处理 HTML 表格标记的评估有点粗略——听起来并没有充分利用屏幕阅读器提供的表格工具。
也不应该这样——这是用户的特权,而不是作者的。
作为有视力的人,我可以根据需要按行或按列浏览表格。在比较表的情况下,我可能会跳过表格,在浏览过程中检查列和/或行标题。
屏幕阅读器中的表格导航工具提供了类似的体验。虽然屏幕阅读器当然可以按行逐行读出整个表格,但还有很多其他方法可以读取它。例如,我可以
使用方向键导航,一次听到一个单元格
将我的位置重置到表格的开头
跳回到一行的开头或一列的顶部
扫描列和行标题(例如,跳到行的开头,然后向上或向下移动)
询问当前单元格的行和列标题(这利用了
<th>
和scope
)询问当前单元格的位置(行号和列号)
完全忽略表格,并跳过它
发现页面上的其他表格,并跳到我想要的表格
工具的确切范围在不同的屏幕阅读器之间有所不同(它们被调用或宣布的方式也是如此),但总体上是相似的。ChromeVox 提供了我提到的所有表格功能,但据我所知,它并没有充分利用
thead
和tfoot
。