React-virtualized: Improve accessibility: using a <table> element at the top-level

Created on 20 Sep 2017  路  5Comments  路  Source: bvaughn/react-virtualized

My organization is using react-virtualized with an application that must support screenreaders using JAWS. While react-virtualized has excellent support for keyboard navigation (tab-index), and adds the proper role/aria-labels, it is still not properly read by JAWS or mac voiceover. Problems:

  • "table mode" is not usable. Unable to read/navigate cell-by-cell
  • Interactive elements (links, buttons, etc) are not read by the screenreader, even when tabbable
  • Screenreader will not provide context on number of columns/rows, and where you are currently focused within the table.

In the end, it seems that no matter what aria-labels and roles are used, a screenreader won't read and give the same functionality as a full on table. Changing the top level element to <table class="ReactVirtualized__Table" role="grid"> resolved all three of my problems. Note: all children remain as <div>s, so no <tr>, <td> etc need be used.

Example audio from Jaws with the current react-virtualized implementation:
https://drive.google.com/open?id=0BxS1c0ZghPGvcGdjQ1FqRHpYMjg

Example audio from Jaws with the new <table> implementation:
https://drive.google.com/open?id=0BxS1c0ZghPGvaC03VGktZ0dXMlE

My question to you is: Is there any reason this would be a bad idea that I haven't considered? If not, then I'll open a PR to the library to make this change.

Most helpful comment

We were running into a similar issue with screen readers not reading but as soon as we added role="Tabpanel" to the List component everything worked with no issues. Noting here incase it helps someone else. 馃憤

All 5 comments

My question to you is: Is there any reason this would be a bad idea that I haven't considered?

Hm, it would be invalid HTML.

To be honest, I don't have a ton of context on the accessibility side of this- to understand why an HTMLTableElement type is specifically needed vs additional (or modified) aria roles. It seems like the latter should be sufficient.

@joofsh Would it be acceptable to use two <table>s for header and Grid?

<div class="ReactVirtualized__Table" role="grid">
  <table role="header"  class="ReactVirtualized__Table__header" role="rowgroup">
    <thead role="rowgroup">
      <tr role="row">
        <th role="gridcell">Foo</th>
        <th role="gridcell">Bar</th>
      </tr>
    </thead>
  </table>
  <div class="ReactVirtualized__Grid ReactVirtualized__Table__Grid">
    <table  role="rowgroup" class="ReactVirtualized__Table__header">
      <tbody role="rowgroup">
        <tr role="row">
          <td role="gridcell">Solution</td>
          <td role="gridcell">42</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

I understand the usage of divover tabledue to the styling problems regarding scrolling etc. But if two tables would solve the problem, maybe we could join our efforts: #817

We were running into a similar issue with screen readers not reading but as soon as we added role="Tabpanel" to the List component everything worked with no issues. Noting here incase it helps someone else. 馃憤

It sounds like Tommy's suggestion of specifying role="Tabpanel" is a valid workaround for this issue that does not require dramatically changing the HTML structure. (I'm curious if this also resolves the issue you commented on, @bluefuton?)

I'm going through and closing inactive issues this weekend and I'm including this one since it seems inactive for a few months. We can keep chatting here though.

@joofsh Would it be acceptable to use two <table>s for header and Grid?

<div class="ReactVirtualized__Table" role="grid">
  <table role="header"  class="ReactVirtualized__Table__header" role="rowgroup">
    <thead role="rowgroup">
      <tr role="row">
        <th role="gridcell">Foo</th>
        <th role="gridcell">Bar</th>
      </tr>
    </thead>
  </table>
  <div class="ReactVirtualized__Grid ReactVirtualized__Table__Grid">
    <table  role="rowgroup" class="ReactVirtualized__Table__header">
      <tbody role="rowgroup">
        <tr role="row">
          <td role="gridcell">Solution</td>
          <td role="gridcell">42</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

I understand the usage of divover tabledue to the styling problems regarding scrolling etc. But if two tables would solve the problem, maybe we could join our efforts: #817

Hi @joofsh, when you said 'scrolling', were you referring to having a scroll bar within part of a table (e.g. a vertical one for all rows except for the header row)? What other styling problems are there that prevent usage of <table/> element?

Was this page helpful?
0 / 5 - 0 ratings