Tables and accessibility

Spanning cells and complex headers

Use colspan, rowspan, header groups, and explicit header associations without losing the row-and-column relationships in a table.

9 minute lesson

~~~

Some tables need a header that covers several columns.

Use colspan to make one cell span them:

<table>
  <caption>Workshop registrations</caption>
  <thead>
    <tr>
      <td></td>
      <th id="spring" colspan="2" scope="colgroup">Spring</th>
    </tr>
    <tr>
      <th id="workshop" scope="col">Workshop</th>
      <th id="april" scope="col">April</th>
      <th id="may" scope="col">May</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th id="html" scope="row">HTML</th>
      <td headers="html spring april">18</td>
      <td headers="html spring may">24</td>
    </tr>
  </tbody>
</table>

colspan="2" makes the Spring header cover April and May.

scope="colgroup" says Spring labels a group of columns. The headers attribute makes the complete relationship explicit for each data cell.

The value of headers is a space-separated list of id values from header cells.

rowspan works in the other direction. It makes a cell cover several rows.

Be careful with both attributes. A table that looks obvious as a grid can become difficult to understand when read one cell at a time.

My advice is to keep tables simple. If you need many merged cells and long headers values, consider splitting the data into two smaller tables.

Check the relationships

Choose one data cell and answer:

  • which row header describes it?
  • which column header describes it?
  • does a grouped header also apply?

If you cannot answer quickly, the table needs a simpler structure.

Lesson completed