A "complex" data table is a table with three or more levels of headings. (Note: The data in the example below are fictional.)
| Summer | Winter | |||
|---|---|---|---|---|
| DC | Fairfax | DC | Fairfax | |
| High | 102 | 102 | 70 | 68 |
| Low | 74 | 72 | -1 | -2 |
In the example above, there are three headers that are associated with each data cell. For example the cell that says "74" is associated with Summer, DC, and Low.
Ignoring, for now, the additional markup that is necessary to make this table accessible to screen readers, the code for this table is shown below:
<table width="327" border="1" class="normal">
<caption>
Temperatures in the DC Area
</caption>
<tr>
<th rowspan="2"> </th>
<th colspan="2">Summer</th>
<th colspan="2">Winter</th>
</tr>
<tr>
<th>DC</th>
<th>Fairfax</th>
<th>DC</th>
<th>Fairfax</th>
</tr>
<tr>
<th>High</th>
<td>102</td>
<td>102</td>
<td>70</td>
<td>68</td>
</tr>
<tr>
<th>Low</th>
<td>74</td>
<td>72</td>
<td>-1</td>
<td>-2</td>
</tr>
</table>
If you look closely at the code above, you'll notice that the top row has
only three cells, whereas all of the other rows have five. That's because
two of the cells use the colspan attribute. The cells are spanning
(or merging) more than one cell together. In this case, they are spanning
2 cells. A similar attribute, called rowspan, allows a cell to span over
multiple rows.
It can be tricky to type all of this out by hand, and to remember which header cells are spanning which columns, but if you can keep it all straight, you can create quite complex tables.
Now that you know the basic technique for creating complex tables, a good rule of thumb is to avoid creating complex tables, to the extent possible. Simple tables are easier to create, easier to understand, and easier to make accessible to people with disabilities. That doesn't mean that complex tables are wrong, but it does mean that you should use them only when necessary.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 2.5 License.