vocab.design

accessibility · tables

Header association

also called scope attribute (html), headers attribute (html), row header (community), column header (community)

The markup that ties a data cell to its row and column headers, so a cell read on its own still says what it is.

A screen reader does not read a data table the way an eye does. It moves cell by cell, and at each stop it says the cell’s contents plus whatever headers that cell is associated with. Land on an unassociated cell and you hear “42”. Land on an associated one and you hear “Revenue, Northwest, 42”, which is the same information a sighted reader gets for free by glancing up and left. Header association is the markup that makes the second announcement possible, and there is no way to infer it from appearance: a bold grey row across the top of a table is a visual convention, not a relationship, and a td styled to look like a heading associates nothing at all.

The cheap mechanism is scope. Put scope="col" on the cells in the header row and scope="row" on the first cell of each body row, use th rather than td for both, and a simple grid is done. The expensive mechanism is id and headers: every header gets an id and every data cell lists the ids that describe it, in the order they should be spoken. It is laborious and it is worth reaching for exactly once, when the table has a header spanning several columns above a second row of headers. That upper level is the one scope="col" does not reach, scope="colgroup" reaches only where support is good, and headers reaches reliably, which is why a quarter-over-quarter table with Revenue and Units under each quarter is the canonical case for it.

Two neighbouring terms make the association visible rather than audible, and neither replaces it. A sticky header keeps the header row on screen as the body scrolls, which helps an eye and does nothing for a cursor walking cells. Sort state tells a reader which column the table is ordered by, which is a different fact about the same header cell. Both assume the header is a real th in the first place, so the association is the thing to get right first and the thing most often skipped.

The two failures worth watching for are a layout grid pretending to be a table, where there are no header cells to associate with, and a table where every cell in the top row is a th but nothing carries scope, which is halfway and announces nothing. Both look correct in a screenshot. The test is to read one cell out of context and ask whether it still says what it is.

Which word?

If you wantsay
a table cell must announce which column it is inheader association
a wide table where you lose track of the rowfrozen column

Related

See also: Data table · Sort state

Sources