Skip to content

A Seat at the Table: Building Accessible Tables for Everyone

Tables are powerful tools for organizing and presenting information clearly and concisely. Still, if not designed correctly, they can also be a source of frustration for people with disabilities, especially screen reader users. 

This blog post will focus on simple table structures, covering essential elements like table headers, captions, and proper HTML markup.

Simplicity Counts

Keep the table as simple as possible to make it as accessible as possible. One way to accomplish this is to include a single header, either in the first column or the first row.
Representation of a table with 4 rows and 4 columns. The header row is shaded in gray.

Use Captions

A table caption appears above or below the table and briefly describes its contents, similar to a paragraph heading. It helps users understand the table's purpose and scope. 

Captions help users locate tables and decide if they want to read them. This is especially important for screen reader users as they navigate table cell-by-cell. A large, complex table can be very time-consuming to read when using a screen reader.

In HTML, the <caption> element specifies the caption of a table. For example, this HTML snippet

<table width="30%">
<caption><strong>Number of brown and blue socks in two sizes</strong></caption>
<tr bgcolor="#cad1db">
    <td>-</td>
    <th>Brown Socks</th>
    <th>Blue Socks</th>
    <th>Total Socks</th>
</tr>
<...>
</table>

renders this table.

Number of brown and blue socks in two sizes
Four columns, four rows. Column headers are Brown Socks, Blue Socks, Total Socks. Row headers are Size 0-8, Size 8-12, Total.

Header Rows and Header Columns

A header row is the first row at the top of a table. The cells within a header row contain words or phrases that identify what data can be found in the column below. For example, a cell in a header row with the word "Date" gives the user a clue that the data found in corresponding cells will be numbers formatted as dates.
Representation of a table with three columns and four rows. The column headers are Date, Event, Venue.
Image courtesy of W3C, Table Tutorial

A header column is the first column on the left side of a table. Column header cells function the same way as a header row.

Representation of a table with three columns and four rows. The row headers are Date, Event, Venue.

Image courtesy of W3C, Table Tutorial

When navigating a table, the screen reader announces each cell individually and links it to the appropriate header, helping the user understand the relationship between the header and the associated data cells.

Here are some best practices for using header rows and columns: 

  • Use only one header row and / or one header column per table. 
  • Distinguish column and row headers with a bold font slightly larger than the font used for the data.
  • Apply shading, making sure proper color contrast is maintained.
  • Using the TH elements without the scope attribute is sufficient for simple tables with headers in the first row or column.

Scope Attribute

The scope attribute associates header cells with corresponding data cells in complex tables. For example, if a table contains a row header and a column header, the scope attribute should be used to "connect" the proper data point to the appropriate header.

In the example below, the header row and header column are shaded, and bold text is used for the header cell labels. 

Number of brown and blue socks in two sizes
Four columns, four rows. Column headers are Brown Socks, Blue Socks, Total Socks. Row headers are Size 0-8, Size 8-12, Total.

The HTML for this table would look like this:

	<table width="30%">
	<caption><strong><i>Number of brown and blue socks in two sizes</i></strong></caption>
	  <tr bgcolor="#cad1db">
	  <td><div style="visibility: hidden;">intentionally blank</div></td>
	    <th scope="col">Brown Socks</th>
	    <th scope="col">Blue Socks</th>
	    <th scope="col">Total Socks</th>
	  </tr>
	  <tr>
	 <th scope="row" bgcolor="#cad1db">Size 0-8</th>
	    <td>15</td>
	    <td>20</td>
	    <td>35</td>
	  </tr>
	   <tr>
	 <th scope="row" bgcolor="#cad1db">Size 8-12</th>
	    <td>25</td>
	    <td>10</td>
	    <td>35</td>
	  </tr>  
	   <tr> 
	<th scope="row" bgcolor="#cad1db">Total</th>
	    <td>40</td>
	    <td>30</td>
	    <td>30</td>
	  </tr>
	  </table>

For more information on captions and the scope attribute, see Coding for Beginners: Tables #9— Accessibility for Tables—The caption element and scope attribute on YouTube.

Avoid Blank and / or Merged Cells

Blank data cells can be approached differently. It is not uncommon to have a blank data cell in a table. The problem is that different screen readers handle them differently. JAWS will voice "blank" when it comes across a blank cell in a table. However, NVDA will not voice anything. It will just push you to the next cell in line and read the appropriate column header as long as Scope is defined. ~ Dax Castro, "How to handle blank data cells in accessible tables"

Table representation with Alternative Values, JAWS and NVDA as column headers.  n/a is En slash Uh in JAWS En slash A in NVDA N.A. is N dot A in JAWS and N dot A in NVDA na is Nah in JAWS and En A in NVDA An empty cell is called blank in JAWS and nothing is voiced in NVDA Not applicable is Not applicable in JAWS and Not applicable in NVDA No value is No value in JAWS and No value in NVDA - is Dash in JAWS and nothing is voiced in NVDA 0 is zero in JAWS and zero in NVDA

Image courtesy of https://www.accessibilityunraveled.com/

Screen readers read table content using a top-down, left-to-right approach. Merged or split cells can interfere with this order, making your content challenging to navigate. To ensure a smooth reading experience, avoid merged or split cells and consider using multiple simple tables or restructuring your content.

Data Structure

While table structure itself is important, so is the structure of your data. Here are a couple of best practices that help ensure your data is readable and understandable:

  • Always left-align your data text. The only exception is your header text, which can be subject to organizational style guides and personal choice. Remember that centered and justified texts are much more challenging to read, and for some with cognitive impairments, they are impossible to read.
  • HTML tables are designed for data, not design. The W3C suggests avoiding tables for layout to keep content and style apart.
  • Always right-align the number decimals according to the position of decimal points to make it easier to read. For example,
    Table representation to illustrate decimals lined up. All numbers are right aligned in each cell, ensuring that all decimals are in a single, straight vertical line view.

These best practices will help you create beautiful, accessible tables. Remember, this post focused on simple tables. There is a lot more to learn the more complex your tables become. The W3C’s Table Tutorial has a section on irregular headers, multilevel headers, and a list of tips and tricks to help you build an even more accessible and usable table.

Resources

Maggie Vaughan, CPACC
Content Marketing Practitioner
DubBot