使表格行或单元格被表格读取为可点击

Jus*_*ser 0 html datatable accessibility screen-readers

嗨,我正在处理一个表格,我想提高它的可访问性,但问题是它是使用具有“onClick”属性的表格行创建的,并且在使用屏幕阅读器(例如 VoiceOver、NVDA)阅读单元格和表格时或 JAWS 它不会将该行读取为可点击或任何会告诉用户单击该行会将他带到另一个页面的标志。

该表是由 JQuery Datatables 动态创建的,该表的片段如下所示:

<div id="DataTables_Table_1_wrapper" class="dataTables_wrapper" role="grid">
  <table
    class="list lista table table-bordered table-hover dlaList component-editable dataTable"
    data-editable-id="dla28475"
    style="width: 900px"
    id="DataTables_Table_1"
  >
    <thead>
      <tr role="row">
        <th
          class="sorting"
          tabindex="0"
          rowspan="1"
          colspan="1"
          style="width: 230px"
        >
          Activities
        </th>
        <th
          class="sorting_asc"
          tabindex="0"
          rowspan="1"
          colspan="1"
          style="width: 570px"
          aria-sort="ascending"
        >
          Description
        </th>
        <th
          class="sorting"
          tabindex="0"
          rowspan="1"
          colspan="1"
          style="width: 100px"
        >
          Status
        </th>
      </tr>
    </thead>
    <tbody role="alert" aria-live="polite" aria-relevant="all">
      <tr class="odd" onclick="functionForEvent();">
        <td class="">
          <div class="input-sm" status_id="undefined">Blah Blah</div>
        </td>
        <td class="sorting_1">
          <div class="input-sm" status_id="undefined">Blah blah</div>
        </td>
        <td class="">
          <div class="input-sm" status_id="undefined">blah blah</div>
        </td>
      </tr>
    </tbody>
  </table>
</div>
Run Code Online (Sandbox Code Playgroud)

我目前创建的解决方案是添加一个<a></a>sorrounding 每个<td>因此使屏幕阅读器说“链接”,但我看到其他表格说“可点击”而无需链接,但我不知道他们是如何通过查看做到的在 HTML 中,它们似乎只是在 tr 元素上带有 onClick 的常规表格。

这里的一个坏迹象可能是“角色”属性破坏了我所读到的语义,该表不是由我创建的,因此我不知道是否可能是这种情况。

Gra*_*hie 5

序言

向 OP 道歉 如果该行旨在将人们带到另一个页面,则此答案中的一些内容可能会产生误导。

首先对于下面的选项 1 和 2交换<button>s <a>。不需要事件侦听器,也不需要onclick锚点做所有需要的事情。

对于选项 3,我会在解释这会将您带到新页面的文本中添加一点额外的内容。

如果您选择使用列文本作为可访问文本(即不要覆盖aria-label),那么您应该添加aria-describedby并添加一个段落,上面写着“,单击以在新页面中打开”。

<p id="newPageText" class="visually-hidden">click to open (new page)</p>

<tr class="odd" tabindex="0" aria-describedby="newPageText">
        <td class="">
          <div class="input-sm" status_id="undefined">Blah Blah</div>
        </td>
        <td class="sorting_1">
          <div class="input-sm" status_id="undefined">Blah blah</div>
        </td>
        <td class="">
          <div class="input-sm" status_id="undefined">blah blah</div>
        </td>
      </tr>
Run Code Online (Sandbox Code Playgroud)

对于屏幕阅读器,这将显示“废话,废话,废话,单击以在新页面中打开”。然后,这会填充屏幕阅读器因无法使用锚点而使用语义(我们丢失的)读出的信息

简答

您没有听到任何通知的原因是您的行不可聚焦。

一个项目必须是可聚焦的,以便有一个点击公告。

添加tabindex="0"会解决这个问题,键盘的用户,为鼠标用户,你应该添加cursor: pointer.tr:hover{}规则,以你的CSS。

但是,有更好的选择,详情如下。

长答案

有一整行可点击并不是最好的主意。

但是,它仍然比我在“不该做什么”部分中详述的其他一些选项更可取,因此我将其包含在下面的第三个选项中。

以下是从预期行为和可访问性与实施时间的最佳到最差的几个选项(第二个选项是最佳选项,但可能需要付出很多努力来实施)。

1. GOOD - 改为向列添加按钮 - 易于实现

在行的开头(或结尾,如果更合适)添加一列,然后添加<button>到该列中以执行操作。

删除该行上的点击处理程序并将其附加到<button>(也将其更改为 JavaScript 中的事件侦听器而不是内联onclick以简化可维护性)。

在此按钮中,我们为屏幕阅读器用户/纯文本浏览器用户添加了一些视觉上隐藏的文本,以使行关联清晰。

我推荐可视化隐藏文本,因为它仍然aria-label可悲的强大得多(尽管情况越来越好!)并且具有一直工作回到 ie6 的额外好处(尽管如果您的网站在 IE6 中工作,那么您比我更好!: -) )!

您可以在可视化隐藏<span>在服务器上构建字符串或通过 JavaScript 构建它。

如果有一个特定的列足够独特/描述性足以知道您正在编辑的内容,则它不需要包含所有行信息。我只将所有 3 列的文本添加到示例中,因为我不知道您的数据。

示例 1

<p id="newPageText" class="visually-hidden">click to open (new page)</p>

<tr class="odd" tabindex="0" aria-describedby="newPageText">
        <td class="">
          <div class="input-sm" status_id="undefined">Blah Blah</div>
        </td>
        <td class="sorting_1">
          <div class="input-sm" status_id="undefined">Blah blah</div>
        </td>
        <td class="">
          <div class="input-sm" status_id="undefined">blah blah</div>
        </td>
      </tr>
Run Code Online (Sandbox Code Playgroud)
.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 */
}
Run Code Online (Sandbox Code Playgroud)

这是所有设备中最强大的方式并且易于实施,这就是为什么它是最推荐的,但是它增加了很多制表位,如果您有时间实施网格模式,则不是最佳选择

2. BEST - 推荐方式(如果不能添加列) - 难以实施

使用role="grid"并遵循网格模式。

role="grid"具有良好的屏幕阅读器支持并且是语义上最合适的角色。

这里需要更多,因为您需要启用键盘控制,例如使用箭头键等。

然后,您将在页面上添加一个视觉上隐藏的段落,上面写着“单击以编辑”并给它一个id(例如id="editText")。

然后在每个上<td>添加,aria-describedby="editText"以便<td>阅读它的内容,然后是“点击编辑”。

此时,您只需在 JavaScript 中添加一个事件侦听器来侦听点击(而不是具有内联onclick属性。)如果您不确定,这个答案应该让您了解如何为每个事件添加一个事件侦听器<td>

W3C 示例

没有我的例子,因为这种方式需要比 Stack Overflow 答案证明的更多的工作!呵呵。但是,如果您可以使其成为可重用的组件,那么在整个站点中重用是一种很好的模式。它有一个显着的优势,它只引入了一个制表位。

3. AVERAGE - 如果您不能使用role="grid"或添加列的可能方式。

添加tabindex="0"<tr>.

这将使该行可聚焦,然后当用户通过键盘聚焦该行时宣布“可点击”。

对于谁使用屏幕阅读器使用鼠标的用户仍然会有没有点击公告但这是cursor: pointer.tr:hover{}是(改变光标,并确保在视觉上很显然这是一个可点击的区域与一些可见的指示鼠标悬停时)。

所有行列将被一个接一个地读出作为焦点时的文本,这可能不合适,因此您可能希望aria-label在支持它的浏览器中添加一个作为覆盖。

tr:focus如果这样做,请确保您将指示器设置为可见且清晰。

<table>
<tbody>
      <tr class="odd">
       <td>
           <button>
               Perform Action
               <span class="visually-hidden">
                   Column 1, Column 2, Column 3
               </span>
           </button>
       </td>
        <td class="">
          <div class="input-sm" status_id="undefined">Column 1</div>
        </td>
        <td class="sorting_1">
          <div class="input-sm" status_id="undefined">Column 2</div>
        </td>
        <td class="">
          <div class="input-sm" status_id="undefined">Column 3</div>
        </td>
      </tr>
    </tbody>
    </table>
Run Code Online (Sandbox Code Playgroud)
tr:hover{
   cursor: pointer;
   background-color: #cccccc;
}
tr:focus{
   border: none;
   outline: 2px solid #333;
   outline-offset: 2px;
}
Run Code Online (Sandbox Code Playgroud)

由于引入了很多制表位,以上是最简单的修复,但从可访问性的角度来看并不理想。尽管在只有几行的表上它仍然可以使用。


什么不该做

不要在锚中包裹一行 <a>

无论如何,这在语义上是不正确和无效的 HTML。这会导致某些屏幕阅读器出现问题。

请勿role="alert"<tbody>.

如果您试图提醒屏幕阅读器注意表格中的更改,请提出另一个问题,详细说明您要宣布哪些更改,我会帮助您解决这个问题。

目前,它将在页面加载和每次更改时开始读取表格。即使您只添加一行等,它也会再次读取整个表格,并且每次应用过滤器时都可能会读取整个表格。正如您可以想象,对于屏幕阅读器用户来说,这将成为一场噩梦!

不要添加<buttons>到每个<td>或使每个<td>(单元格)可点击tabindex="0"

对于依赖Tab按键导航的键盘用户(即非屏幕阅读器用户)来说,这将是一场噩梦。

您添加了太多不必要的制表位,页面可能会变得无法使用。

其他一些观察/建议

  1. 如果表格很长并且您最终使用选项 1 或 3(为每一行添加一个制表位),请确保skip link表格前有一个。
  2. 删除role="alert"aria-live="polite"如前所述。
  3. 使用您的可排序列标题,您最好<button><th>触发排序功能的 中添加一个,它带有内置的所有焦点状态等。
  4. role="grid"<div>- 中删除-<table>如果您使用该模式(我提供的选项 2),则应改为使用该模式。
  5. 使用事件处理程序而不是onclick属性 - 只是性能和可维护性的一般提示 - 与可访问性无关!