Eric Niquette

What makes a table accessible?

For a table to be considered accessible, it should consist of linear data that titled by header cells, and ideally include a caption. Supplementary features such as colour banding, summaries, captions, and other explanatory notes can also be used to further enhance a table's accessibility.

Conversely, a table that is lacking structure, is marked up incorrectly, or otherwise has a non-linear reading order is considered an accessibility barrier and would be significantly difficult to parse using assistive tools such as screen readers.

How screen readers parse tables

When navigating to a table, screen readers provide the user basic information on the table's structure, such as the number of rows and columns it contains as well as the table's caption and summary, if present.

The following is an example of how a screen reader interprets a simple table.

Table 1. Prevalence of disability in Canadians by age group
Age Prevalence of disability
15 to 24 years 13.1%
25 to 44 years 15.3%
45 to 64 years 24.3%
65 to 74 years 32.0%
75 years and over 47.4%

Using tables to design layouts

The goal of a layout table is typically to create a grid-like arrangement rather than to present data. The practice is commonly-seen in word processors and on old legacy websites, before the advent of CSS. As a design tool, tables provide an easy way to align content to a grid; cells can be split, merged, or resized to suit most needs.

While modern screen readers have become adepts at distinguishing between data and layout tables, the preferred approach is to utilize modern, accessible CSS techniques such as the grid and flex layouts, or using floats where appropriate.

When a table is used to layout a design, the table's reading order may not reflect the code's order. This can cause the reader to move through the content in an erratic way that doesn't follow the on-screen flow.

In the following illustration, notice the order in which the screen reader would interpret the table, and how it differs from the content's natural flow.

By design, tables also retain their layout when resized; you wouldn't want your cells to shift around and break the intended order. This also means that tables don't reflow their layout to fit the viewport; they can only compress or expand. When a table requires a larger viewport than is available, the contents will break into multiple lines or cause horizontal scrolling.

How to minimize the impact of layout tables in HTML

When a screen reader inspects a table with the goal of determining whether its used to present data or for layout, it does so with a series of checks and by searching for certain giveaways like header cells, captions, and summaries.

If you must use a layout table, ensure that you are not providing any supporting features that could potentially trigger the interpretation as data. Convert any <th> cells to <td>, and remove both the <caption>; element and summary attribute.

Tables can also be assigned a role of presentation, which strips it of its semantic value. In other words, it treats the table as if it were non-semantic element, such as an empty container.

<table role="presentation">
  <tr>
    <td>
      <h1>My presentation table</h1>
    </td>
  </tr>
</table>

Headers

Table headers are an important element to visual and non-visual users alike as they provide context on the type of content a cell contains. For example, the column header cell titled “E-mail address” informs the user to expect data formatted as an e-mail address in its associated cells.

Tables can contain a header row, a header column, or both. The <th> element is used to indicate a header, rather than a <td> data cell. The scope attribute defines whether the cell applies to the row, column, or both.

<table>
  <thead>
    <tr>
      <th scope="col">Course</th>
      <th scope="col">Professor</th>
      <th scope="col">Day</th>
      <th scope="col">Time</th>
      <th scope="col">Room</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">English</th>
      <td>John Doe</td>
      <td>Monday</td>
      <td>11:20 am</td>
      <td>503-B</td>
    </tr>
  </tbody>
</table>

Headers in complex tables

Generally speaking, a table is deemed complex when its data is not linear, typically due to the presence of cells that have been split or merged together. In some cases, tables may also be nested in another table.

For accessibility, complex tables should be avoided and instead broken down into smaller tables instead. In cases where this may not be possible, header cells will have to be manually associated to their respective data cells. This can be a grueling task if you lack the tools to somewhat automate the process.

To assign header cells, each header is provided an ID. This is then, with the headers attribute, associated to data cells.

<table>
  <thead>
    <tr>
      <th colspan="2" id="q1">First quarter</th>
      <th colspan="2" id="q2">Second quarter</th>
    </tr>
    <tr>
      <th id="in_q1" headers="q1">Income</th>
      <th id="out_q2" headers="q1">Expenses</th>
      <th id="in_q2" headers="q2">Income</th>
      <th id="out_q2" headers="q2">Expenses</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td headers="q1 in_q1">5.6</td>
      <td headers="q1 out_q1">4.2</td>
      <td headers="q2 in_q2">4.4</td>
      <td headers="q2 out_q2">4.1</td>
    </tr>
  </tbody>
</table>

Empty cells

In general, care should be taken to avoid leaving empty cells in a data table. Some screen readers will opt to skip empty cells, breaking the linear flow of data. Instead, provide useful information to the user. If the cells contains no value, opt for a text value of "0" or "Null".

It should be noted that some screen readers will also fail to announce cells that only contain a dash.

Avoid populating a cell to indicate a state. Using a cell as a makeshift checkbox or using "X" is not descriptive to users relying on screen readers and assistive devices. Use explicit, descriptive text such "Pass", "Included" to provide a state or condition.

Captions

A table caption is a short, introductory title that appears before the table and provides context or a brief description of the contents found within. Table captions often include a reference number such as "Table 1", though this is not required.

In HTML, the caption element must be introduced immediately following the table's opening tag.

<table>
  <caption>Table 1. My table caption</caption>
  <thead> [...]

If your table contains an explanatory note, it should be found in the caption as it is typically provided before the table itself in order to provide context to the user.

<table>
  <caption>Table 1. Financial yearly returns<br>
  Includes partial fourth quarter values</caption>
  <thead> [...]

Table structure

Tables can be structured in three content sections: the head, body, and footer.

The head of a table normally consists of header rows and is marked with the <thead> element. The body, where the data cells reside, is indicated with the <tbody> element. Finally, the footer is where you'll typically find elements such as totals and calculations. The footer is marked with the <tfoot> element.

<table>
  <caption>2022-2023 Financial Summary</caption>
  <thead>
    <tr>
      <th scope="col">Year</th>
      <th scope="col">Income</th>
      <th scope="col">Expenses</th>
      <th scope="col">Value</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">2022<td>
      <td>5.6</td>
      <td>4.1</td>
      <td>1.5</td>
    </tr>
    <tr>
      <th scope="row">2023<td>
      <td>7.5</td>
      <td>5.5</td>
      <td>2.0</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th scope="row">Total<td>
      <td>13.1</td>
      <td>9.6</td>
      <td>3.5</td>
    </tr>
  </tfoot>
</table>

These elements do not impact accessibility and are primarily used for styling tables and in printing. While it is generally good practice to include them, they can be omitted with little to no impact in most cases.

Conclusion

Designing accessible tables isn't just about following guidelines, it's about creating an inclusive experience for all. By considering compatibility with assistive tools, by using clear and meaningful headings, and by using properly structured data, you ensure that everyone, regardless of ability or disability, can engage with your content.