There are several techniques for creating tables with static header rows, but very few of the examples I have come across are accessible or do not work cross-browser. This post looks at some of the current solutions, and outlines a method using WAI-ARIA to fix the accessibility issues of the more popular techniques.
Author: Gez Lemon
Ideally, this problem should be solved using just CSS by specifying the
display properties on the body of the table (
tbody). This works to an extent, but is difficult to get working cross-browser. Pure CSS Scrollable Table with Fixed Header is an old but good example of a CSS version that works in most browsers and screen readers, but doesn't render properly in IE9.
WAI-ARIA as a repair technique
As having two tables seems to be the most reliable in terms of portability, one solution would be to repair the technique so that it appears as a single table to assistive technologies. Consider a data table that determines calories burned depending on the weight and pace of a runner with the headers in a completely different table so that the main body can be set to scroll, as most approaches appear to use this or a variation on this technique.
The process to repair and merge the table with WAI-ARIA is outlined below:
- Merge the two tables (headings and main data) in a single container that has a role of grid.
- Change the role of the two existing data tables to presentation so they are ignored by assistive technologies.
- Remove hidden headers from the main data table if they have been provided.
- Use the roles row, columnheader, rowheader, and gridcell to create the structure of a single table.
- Use aria-labelledby to create an association between the table and the table's header, so that the table is announced with the context of a heading, similar to a native HTML data table having a
- Unless stated otherwise, a grid is considered editable. The aria-readonly attribute should be used to indicate that it's a read-only data table.
The following is the resulting structure:
Alternatively, the structure could be defined with WAI-ARIA removing the HTML tables completely, as it's far easier to control the
div elements with CSS than the tables.
Accessibility of this solution
This solution works well using JAWS. Unfortunately, it does not work well with VoiceOver on an iPad iOS6 or on a Mac. VoiceOver recognises the table as a single table, but does not map the
rowheader roles as column and row headers properly. In iOS6 they're ignored, and on a Mac they're reported incorrectly (thanks to Steve Faulkner for testing these roles on a Mac with VoiceOver).
The best solution would be to use CSS to scroll the main body while leaving the headers static, but there doesn't appear to be an accessible solution that works cross-browser. If anyone knows of a solution, please post in the comments. As the most popular technique to have static headers in a data table is to put the headers and the table content in two different tables, then this repair technique seems reasonable (or defining the structure with WAI-ARIA alone). It's a shame the WAI-ARIA
rowheader roles are not better supported in VoiceOver, but support is likely to improve.