Advanced Tables: scope, colspan, rowspan, caption
Making Tables Accessible and Flexible
A basic table works, but a well-marked-up table tells screen readers exactly which header belongs to which data cell. The scope, colspan, and rowspan attributes are the key tools.
The scope Attribute
Adding scope to a <th> cell declares whether it is a header for a column (scope="col") or a row (scope="row"). Screen readers use this to announce the correct header when a user navigates a data cell.
<table>
<caption>Q2 Sales Report</caption>
<thead>
<tr>
<th scope="col">Region</th>
<th scope="col">April</th>
<th scope="col">May</th>
<th scope="col">June</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">North</th>
<td>$12,400</td>
<td>$15,200</td>
<td>$18,900</td>
</tr>
<tr>
<th scope="row">South</th>
<td>$9,800</td>
<td>$11,300</td>
<td>$14,100</td>
</tr>
</tbody>
</table>colspan and rowspan
colspan makes a cell span multiple columns; rowspan makes it span multiple rows. The browser will not add extra cells automatically — you must remove the cells that the spanning cell replaces.
<table>
<thead>
<tr>
<!-- spans 2 rows, so no second-row cell needed for Name -->
<th scope="col" rowspan="2">Name</th>
<!-- spans 2 columns -->
<th scope="col" colspan="2">Scores</th>
</tr>
<tr>
<!-- only 2 cells here because Name already spans this row -->
<th scope="col">Midterm</th>
<th scope="col">Final</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Alice</th>
<td>84</td>
<td>91</td>
</tr>
</tbody>
</table>When cells span multiple rows or columns, the number of actual <td>/<th> elements in a row will be less than the visual column count. Count carefully — missing or extra cells cause browser rendering bugs that are hard to diagnose.