Colgroup for complex table with three levels of headers

Colgroup for complex table with three levels of headers

给定一个 table 这样的:

(HTML-code):

<table>
  <thead>
    <tr>
      <th>H1-A</th>
      <th colspan="3">H1-B</th>
      <th colspan="3">H1-C</th>
    </tr>
    <tr>
      <th>H2-A</th>
      <th colspan="2">H2-B</th>
      <th>H2-C</th>
      <th colspan="3">H2-D</th>
      <th colspan="3">H2-E</th>
    </tr>
    <tr>
      <th height="10">H3-A</th>
      <th>H3-B</th>
      <th>H3-C</th>
      <th>H3-D</th>
      <th>H3-E</th>
      <th>H3-F</th>
      <th>H3-G</th>
      <th>H3-I</th>
      <th>H3-J</th>
      <th>H3-K</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
    <tr>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
      <td>data</td>
    </tr>
  </tbody>
</table>


是否可以用colgroup-tag标记headers这个table?换句话说:

列组可以用于 multi-row headers 吗?

我需要标记 headers 以实现可访问性目的,这似乎是此类 table 的唯一选择,因为 headers-attribute 似乎有 poor screenreader-support

我的理解是,你可以用“colgroup”元素来标识列组,但是你不能用它们指定这个header结构,因为“colgroup”元素不能包含其他“colgroup”元素。

我的实验使我得出结论,屏幕阅读器的支持比您描述的更差:支持很差,而且不仅对“headers”属性,而且对 tables作为一个整体,除了最简单的,而且对于最简单的tables来说甚至都不是很好。

更糟糕的是,有时屏幕阅读器确实会为单元格宣布 headers,并宣布错误的 headers(当 table 被正确标记时),导致用户认为某些东西属于一个类别,而实际上它属于另一个类别。

如果我想在能力和 assistive-technology 范围内提供可靠的可理解性,我可能会将数据渲染为 tables,但我会在一些更广泛支持(虽然较少简约) 格式,例如标题和段落。

前言

这并不像我想象的那么简单,我尝试了很多技术,例如典型的 colgroup,然后我什至尝试了 headers attribute,它允许您定义 headers 通过 ID。

经过一番搜索,我发现了这个 example page where someone had tried 3 level column headers (example 3),他们遇到了类似的问题。

经过一番修改后,我确实设法得到了一些可行且看起来不错的东西,但它需要在其他屏幕上进行更多测试 readers,因为我的电脑上只有 NVDA 和 JAWS (目前没有时间测试所有 browser-screen reader 组合)。

可能的解决方案

与任何事情一样,如果我无法使语义元素起作用并且无法使 WAI-ARIA 起作用,那么我会求助于我们的老朋友 aria-hiddenvisually hidden text

我所做的是从屏幕 reader 中完全隐藏 table 中的前两 header 行,然后使用视觉隐藏文本将信息添加回第 3 级headers.

例如,对于第 10 列,我在“H3-K”之前添加“H1-C、H2-E”。

<th scole="col"><span class="visually-hidden">H1-C, H2-E,</span>H3-K</th>

通过这种方式,屏幕 reader 用户可以有效地看到普通的 10 列 table,这很容易导航,但所有相关的 header 信息都会被读出。

例如第一个单元格读作

row 2 H1-A, H2-A,H3-A column 1 data 1a

你显然想要构建一些解决方案(最好是在服务器上,但在紧要关头使用 JS 会被接受table)自动执行此操作以避免出现任何错误。

这不是一个理想的解决方案但这是我能想到的最好的解决方案,也是我会做的,因为至少所有相关信息都会显示在屏幕上reader 用户。

警告: 如果我可以自动执行该过程,我只会使用该解决方案,如果我不能为每列自动生成视觉隐藏文本,我会 什么都不做 并保持 table 原样,因为这里的错误可能比单独留下 table 更不容易发现。

例子

table{
    width: 100%;
}
th{
   text-align: center;
}
th, td{
    border: 1px solid #333;
}

.visually-hidden { 
    border: 0;
    padding: 0;
    margin: 0;
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
    clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
    clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
    white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<table>
  <thead>
    <tr aria-hidden="true">
      <th colspan="4">H1-A</th>
      <th colspan="3">H1-B</th>
      <th colspan="3">H1-C</th>
    </tr>
    <tr aria-hidden="true">
      <th>H2-A</th>
      <th colspan="2">H2-B</th>
      <th>H2-C</th>
      <th colspan="3">H2-D</th>
      <th colspan="3">H2-E</th>
    </tr>
    <tr>
      <th scole="col" height="10"><span class="visually-hidden">H1-A, H2-A,</span>H3-A</th>
      <th scole="col"><span class="visually-hidden">H1-A, H2-B,</span>H3-B</th>
      <th scole="col"><span class="visually-hidden">H1-A, H2-B,</span>H3-C</th>
      <th scole="col"><span class="visually-hidden">H1-A, H2-C,</span>H3-D</th>
      <th scole="col"><span class="visually-hidden">H1-B, H2-D,</span>H3-E</th>
      <th scole="col"><span class="visually-hidden">H1-B, H2-D,</span>H3-F</th>
      <th scole="col"><span class="visually-hidden">H1-B, H2-D,</span>H3-G</th>
      <th scole="col"><span class="visually-hidden">H1-C, H2-E,</span>H3-I</th>
      <th scole="col"><span class="visually-hidden">H1-C, H2-E,</span>H3-J</th>
      <th scole="col"><span class="visually-hidden">H1-C, H2-E,</span>H3-K</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>data 1a</td>
      <td>data 2a</td>
      <td>data 3a</td>
      <td>data 4a</td>
      <td>data 5a</td>
      <td>data 6a</td>
      <td>data 7a</td>
      <td>data 8a</td>
      <td>data 9a</td>
      <td>data 10a</td>
    </tr>
    <tr>
      <td>data 1b</td>
      <td>data 2b</td>
      <td>data 3b</td>
      <td>data 4b</td>
      <td>data 5b</td>
      <td>data 6b</td>
      <td>data 7b</td>
      <td>data 8b</td>
      <td>data 9b</td>
      <td>data 10b</td>
    </tr>
  </tbody>
</table>