Search code examples
htmlaccessibility

How to use `headers` attribute on `<th>` elements?


I see that the <th> element accepts a headers attribute. But I've never seen an example of how to use it. I know how to use it on <td> elements, but not <th> elements.

If I have a table with some rows that are "children" of other rows I believe the typical way of associating the cells of those child rows with the correct headers is to use the headers attribute on all the child rows' <td> cells.

<table>
    <thead>
        <tr>
            <th scope="col">Property</th>
            <th scope="col" id="occupiedColHeader">Occupied</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th scope="row" id="prop1RowHeader" class="parent-row">Apartment complex</th>
            <td>Partly</td>
        </tr>
        <tr>
            <th scope="row" id="unit1RowHeader" class="child-row">Unit 1</th>
            <td headers="prop1RowHeader unit1RowHeader occupiedColHeader">Yes</td>
        </tr>
    </tbody>
</table>

Could I instead use headers on the child rows' row headers like this?

<table>
    <thead>
        <tr>
            <th scope="col" id="propertyColHeader">Property</th>
            <th scope="col">Occupied</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th scope="row" id="prop1RowHeader" class="parent-row">Apartment complex</th>
            <td>Partly</td>
        </tr>
        <tr>
            <th scope="row" headers="prop1RowHeader propertyColHeader" class="child-row">Unit 1</th>
            <td>Yes</td>
        </tr>
    </tbody>
</table>

On a table with just two columns the difference is small. The larger the table though, the more convenient the latter option would be if it works.


Solution

  • Technically, a <th> is a table cell and a table cell could be labeled using the headers attribute but I just tested it with JAWS and NVDA and it doesn't seem to be honored. Using headers on a <td> works great, but in your situation is not needed.

    With typical headers on the column or row, where the column headers are along the top and the row headers along the left edge, even if there are multiple levels of column and row headers, using <th scope="col"> and <th scope="row"> (along with colspan and rowspan if appropriate) is all you need. There is no need to add a headers to the <td> elements.

    I understand the concept you're trying implement. Kind of an indirect heading. That is, if you can get the <th> to be labeled by other table cells using headers, then the cells that use that <th> as their header will also be labelled by those other cells. But it doesn't work.

    The W3C has some good examples of multi-level headers on both the row and column that do not use the headers attribute and another example with multiple headers on different rows that must use the headers attribute.

    I'm not sure why but the W3C calls that first example "irregular" headers even though the headers are regular, just with multiple levels.

    enter image description here

    enter image description here

    And then the second example with several headers on different rows, which I would call "irregular", they call "multi-level".

    enter image description here

    enter image description here

    I think their labels are backwards.

    In any event, here they are: