Search code examples
html-tableaccessibilitywai-ariavoiceover

How do I properly handle accessibility for Html table with no heading row


I'm trying to build a design in app which appears to be tabular data, but does not have a header row. I've attached an image of the design below:

Table design

I've tried to follow the normal markup examples all over the internet, but almost every example expects a header row.
I am building my table such: (with styling left off)

<table>
  <tr>
    <th scope="row">Main Value</th>
    <td></td>
    <td>100.21 g</td>
  </tr>
  <tr>
    <th scope="row">Sub Category 1</th>
    <td>58 %</td>
    <td>58.15 g</td>
  </tr>
  <tr>
    <th scope="row">Sub Category 2</th>
    <td>42 %</td>
    <td>42.08 g</td>
  </tr>
  <tr>
    <th scope="row">Additional Value</th>
    <td></td>
    <td>71 g</td>
  </tr>
</table>

I'd probably move on but then I start to get really bad results using Voice Over on a Mac.

For example, when I'm over Row 2, column 3, I get the heading for row 3 announced: Voiceover reading the wrong heading for the row

Maybe this is a bug?

Maybe these shouldn't be tables or should be composite of multiple tables?

I'd love any ideas for how to get Voice Over to read these well, or any information on how to semantically structure this kind of data.


Solution

  • Data tables always have two axis of information. They always must have an header row and an header column at least. Otherwise, if you can't easily put header rows and columns to label things, even only mentally, semantically speaking, it's not really a data table, even if it visually looks like one, and a more appropriate markup is needed, such as a simple list or a definition list, or just simple text presented in a grid layout.

    In your example, it indeed looks like a real data table, with two piece of information in each row which are always the same across rows. That's even the base definition of a data table: a collection of items for which you always have the same set of properties repeated.

    IF we take the row "subcategory 1" as an example, what are these two values "58%" and "58.15g" ? I need to find what they represent somewhere, and this information should be present in the header row.

    The data might be so obvious for you that you don't need that header row, but it is probably not so obvious for your readers, screen reader users or not by the way.

    So, my recommendation is to add it, and to make it visible on screen. It will also help perfectly sighted users to understand the data. Beyond just understanding the data, it's also the opportunity to add filtering and sorting, and why not column and/or row reordering, very useful if the table is big.

    Just a side note on colspan/rowspan: as a screen reader user myself, I think that, in most of the cases, it's better to have empty cells rather than colspan/rowspan. They often make the navigation much harder for nothing, and it might oblige you to compexify the markup quite a lot to make everything announced correctly. A simple visually hidden "-" can help explicitly telling that the cell is empty or has no meaningful value, if it isn't clear enough.

    A good usecase for rowspan/colspan is when you have several header rows or columns, in order to create groups. Quick example: a first header row with "morning", "afternoon", "evening" and "night", and a second header row with hours from 00 to 23. Otherwise, it's often a bad idea to use colspan/rowspan inside the data themselves.