可访问的 HTML 表格标记,包含多个总行和节标题

问题描述 投票:0回答:1

我的客户想要一个结构如下的数据表: enter image description here

这个想法是表头将粘在整个表上,而帐户标题将粘在表头的正下方,但仅限于它们自己的部分。

这是否可以通过不破坏屏幕阅读器体验的方式实现?理想情况下,有一种方法可以使用语义 HTML 来做到这一点,不需要任何 hack,但我对所有解决方案持开放态度。 这里的主要目标是让键盘用户和屏幕阅读器都能获得这种体验。

标题将允许用户对整个表格进行排序。例如,按成本升序排序会将每个账户下的交易顺序更改为交易 3、2、1 和交易 6、5、4,但账户部分将保持在相同位置。 我不确定这是否会改变事情。

html accessibility wai-aria semantic-markup wcag
1个回答
0
投票

这是一个格式正确的示例

<table>
,来自 HTML 规范

<table>
 <thead>
  <tr> <th> ID <th> Measurement <th> Average <th> Maximum
 <tbody>
  <tr> <td> <th scope=rowgroup> Cats <td> <td>
  <tr> <td> 93 <th> Legs <td> 3.5 <td> 4
  <tr> <td> 10 <th> Tails <td> 1 <td> 1
 <tbody>
  <tr> <td> <th scope=rowgroup> English speakers <td> <td>
  <tr> <td> 32 <th> Legs <td> 2.67 <td> 4
  <tr> <td> 35 <th> Tails <td> 0.33 <td> 1
</table>

Visual description of headers providing a label to cells. Column headers label the remaining column, row headers the remaining row; row group and column group headers label the remaining row group or column group, respectively.

如您所见,一个表可以有多个

<tbody>
元素对应于多个行组。带有
scope="rowgroup"
的标题为剩余行组提供标签。

对于格式良好且易于访问的表格,我们可以像往常一样提供列标题和行标题。更重要的是,我们可以将每个“Account”部分标记为

<tbody>
,并为每个部分提供行组标题:

table {
  border-collapse: collapse;
}
th, td {
  padding: .5rem 1.25rem;
  border: 1px solid black;
}

thead th {
  background-color: #d3deea;
}
tbody th {
  text-align: start;
}
tbody > tr:first-child > th {
  background-color: #a7e3e4;
}
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Cost</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 123</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 456</th>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
</table>

但是,我们不能天真地使单元格粘住,因为边界将保持在原位:

/* Sticky */
thead > tr > th {
  position: sticky;
  top: 0;
}
tbody > tr:first-child > th {
  position: sticky;
  top: calc(1rem + 1lh + 1px); /* Offset by height of `thead > tr` */
}

/* Styling */
table {
  border-collapse: collapse;
}
th, td {
  padding: .5rem 1.25rem;
  border: 1px solid black;
}

thead th {
  background-color: #d3deea;
}
tbody th {
  text-align: start;
}
tbody > tr:first-child > th {
  background-color: #a7e3e4;
}
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Cost</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 123</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 456</th>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 123</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 456</th>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 123</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 456</th>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 123</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 456</th>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 123</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 456</th>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 123</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 456</th>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
</table>

要“解决”边界问题绝对将“边界”放置在顶部。一个简单的解决方案是使用 ::after

 伪元素
作为边框:

/* Sticky */ thead > tr > th { position: sticky; top: 0; } tbody > tr:first-child > th { position: sticky; top: calc(1rem + 1lh + 1px); /* Offset by height of `thead > tr` */ } /* Border of sticky headers */ thead > tr > th::after, tbody > tr:first-child > th::after { content: ""; position: absolute; top: -1px; left: -1px; width: 100%; height: 100%; border: 1px solid black; display: block; pointer-events: none; } /* Styling */ table { border-collapse: collapse; } th, td { padding: .5rem 1.25rem; border: 1px solid black; } thead th { background-color: #d3deea; } tbody th { text-align: start; } tbody > tr:first-child > th { background-color: #a7e3e4; }
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Cost</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 12</th>
    </tr>
    <tr>
      <td>Trx 1</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 2</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 34</th>
    </tr>
    <tr>
      <td>Trx 3</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 4</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 56</th>
    </tr>
    <tr>
      <td>Trx 5</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 6</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 78</th>
    </tr>
    <tr>
      <td>Trx 7</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 8</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 910</th>
    </tr>
    <tr>
      <td>Trx 9</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 10</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 1112</th>
    </tr>
    <tr>
      <td>Trx 11</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 12</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 1314</th>
    </tr>
    <tr>
      <td>Trx 13</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 14</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 1516</th>
    </tr>
    <tr>
      <td>Trx 15</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 16</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 1718</th>
    </tr>
    <tr>
      <td>Trx 17</td>
      <td>20</td>
    </tr>
    <tr>
      <td>Trx 18</td>
      <td>15</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>35</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th colspan="2" scope="rowgroup">Account 1920</th>
    </tr>
    <tr>
      <td>Trx 19</td>
      <td>30</td>
    </tr>
    <tr>
      <td>Trx 20</td>
      <td>20</td>
    </tr>
    <tr>
      <th>Total</th>
      <td>50</td>
    </tr>
  </tbody>
</table>

注意:如果没有 pointer-events: none

::after
 伪元素(“扩展”其父单元格的区域)将捕获指针事件,从而防止事件到达单元格的子级(例如按钮)。

© www.soinside.com 2019 - 2024. All rights reserved.