How to make accessible tables in HTML

Accessible tables

Accessible tables should allow data to be readable

The use of tables as the bedrock of page layout in HTML is well and truly over, having been usurped by divs. This is a good thing because it means that tables can get back to concentrating on their real purpose, which is to display complex data in a simple format. But aren’t tables dreadful for accessibility? No, they are fine for accessibility as long as they are used for their primary purpose and they are used correctly.

In this post we shall look at how to properly code a table so that it is accessible and easy to use.

The data we will use

For the sake of providing an example for this post, I have used a dataset from the UK Meteorological Office from Newton Rigg. Of this data, I am only going to use data from 2006, 2007 and 2008 (for simplicity) and I will be using the maximum temperature, minimum temperature, rainfall and hours of sunshine averaged or totalled for each month. If you want to follow along with this example, you should prepare this dataset in advance.

The theory

In theory, the table should be simple to create but as tables become more complex, so does the markup. In principle, the best way to denote table headings is using an ID attribute, which is then carried over to each table cell that relates to it. In this way, you create a grid address for each table cell similar to the way that MS Excel references each cell in a spreadsheet.

Building the table

First of all, we have to get the table started:

<table id="newton_rigg" caption="Newton Rigg weather data 2006 - 2008, UK Met Office." Summary=”This table shows monthly average maximum and minimum temperatures and total rainfall in millimetres recorded at Newton Rigg weather station between 2006 and 2008.” cols="4">


Note that a caption has been given to provide a reader with an indication of what the table is about. A summary is also provided to identify the purpose of the table. This is used in a similar way to ALT text. Together these two attributes are useful for accessibility purposes to inform those using screen readers and visitors with cognitive disabilities.

Headers or Cells?

There are two types of cells within a table:

Table Header cells <th>

These are used to describe the column/row headers within the table and should be given special attention when defining a table that will meet accessibility requirements.

Table data cells <td>

These are the cells of the table that contain actual data or information that is cross-referenced against the header cells.

Defining header cells <th>

Next, we need to define the header cells that will give each column it’s context. This is done simply by adding two table rows <tr> followed by a series of <th> cells containing the relevant heading.

Once this is done, we can add a class to the <tr> tag so it can be styled later and we can get down to concentrating on making the table accessible.

We have four columns in our table, marked as ‘Month’, ‘Max Temp’, ‘Min Temp’ and ‘Rainfall’. The associated <th> for each of these is given a unique identifier, such as id=”month”. This is what enables screen readers to read table data within context as it reads the cell. It is important to ensure that the id attribute is meaningful and descriptive.

You will also note that there are two rows of headings. This is because the year of data will change, because we are covering three years worth of data. The year <th> spans all four columns, just to make the table a little more complex!

<tr><th id="month">Month</th>

<th id="tmax">Max Temp (&deg;C)</th>

<th id="tmin">Min Temp (&deg;C)</th>

<th id="rfall">Rainfall (mm)</th></tr>

<tr><th id="year" colspan="4">2006</th></tr>

<tr><th id="year" colspan="4">2007</th></tr>

<tr><th id="year" colspan="4">2008</th></tr>

Populating the data

Next we need to populate the data into the table and this is where the ids for the headings are really important.

Each row contains four cells of data. Each of these cells is referenced back to its table headers. So, for example, the first cell is referenced to the year (e.g., 2006) and to the month. Once we have th ids in place, this is fairly simple – we reference them using the headers attribute. In the first column, we would code <td headers=”year month”> whereas the second cell would be <td headers=”year tmax”>.

The order in which the headers attribute calls the column headers is important as this is the order in which a screen reader will read out the context of the data. In this case it will read (for the first row of data in our table) “2006 January, “2006 Max Temp degrees C 5.6, Min Temp degrees C 0.6, Rainfall mm 34.4”….

<tr><td headers="year month">January</td>

<td headers="tmax">5.6</td>

<td headers="tmin">0.6</td>

<td headers="rfall">34.4</td></tr>

<tr><td headers="year month">February</td>

<td headers="tmax" class="tmax">6.1</td>

<td headers="tmin" class="tmin">1.0</td>

<td headers="rfall">63.9</td></tr>

While this is a bloated way of making a table accessible, at the moment it is the only reliable way of doing so. Future changes in HTML 5 may refine and change this method but at the moment (and until screen readers are updated in line with the HTML standards) this is the most likely method to work.

You can see the finished table from this example here and view the complete code by selecting ‘view source’ in your browser. Note, I have styled this example page to make it easier to see how the data is structured.