Table headers missing

Pattern Checker

What does this mean?

This is shown when a table has been used but no headers have been set.

For example, you might have a table like this:

<table>
    <tr>
        <td>Date</td><td>Amount</td> 
    </tr>
    <tr>
        <td>June 2024</td><td>£400</td> 
    </tr>
    <tr>
        <td>July 2024</td><td>£550</td> 
    </tr>
    <tr>
        <td>August 2024</td><td>£600</td> 
    </tr>
</table>

In the example above we do have the copy for the column headers - "Date" and "Amount" - but they are not marked up correctly - they are just standard cells (td). They might even be styled to look like headers but without the correct markup they won't perform in the same way.

Impact on users

Column or row headers are especially helpful to screen-reader users.

When a screen-reader user first encounters a table with missing headers all that is announced is that it is a table. No indication of the size of the table is given to the user.

Inside a table a screen-reader user needs to know which row or column they are in - otherwise they would continually have to move to the header title to check.

With our bad example table because the headers are not identified, when a screen-reader moves from the "July 2024" cell to the "£550" cell, all they hear is "£550", making the table very difficult to use. The more rows or columns there are the more difficult it becomes for screen-reader users.

Note some screen-readers might actually try to work out if the table is trying to show tabular data and try to assign headers themselves. This is not widespread and can be prone to error so it is always best to mark up your tables correctly.

How to fix

Ensure you are using a table for the correct reasons - look at other options for layout if a table is not appropriate. For example look at using a summary list or a grid layout instead of a table.

Where a table is used it should have headers to indicate what each column or row represents. If it does not have suitable cells which can be used as headers then add them. Use th instead of td for the column or row headers.

If we add the correct markup:

<table>
    <tr>
        <th>Date</th><th>Amount</th> 
    </tr>
    <tr>
        <td>June 2024</td><td>£400</td> 
    </tr>
    <tr>
        <td>July 2024</td><td>£550</td> 
    </tr>
    <tr>
        <td>August 2024</td><td>£600</td> 
    </tr>
</table>

Now when the screen-reader user first encounters the table with headers it will now be announced with a count of how many rows and columns it has. Before we added the headers this information was not announced.

Crucially inside the table instead of just hearing the cell contents when moving between columns, screen-reader users will now have the column header for the column they are entering announced. For example when moving from the "July 2024" cell to the "£550" cell they will hear "Amount £550".

Additional information

Whilst the direction of the header is inferred by its placement, it is suggested you also add scope="col" to the th for column headers and scope="row" for row headers to ensure they are correctly related to the cells.

For example:

<table>
    <tr>
        <th scope="col">Date</th><th scope="col">Amount</th> 
    </tr>
    <tr>
        <td>June 2024</td><td>£400</td> 
    </tr>
    <tr>
        <td>July 2024</td><td>£550</td>
    </tr>
    <tr>
        <td>August 2024</td><td>£600</td>
    </tr>
</table>

References

Classification

Level: warn
Tagged: best-practice

See all issues