Skip to content

Complex Data Tables

8 minute read

Last updated:

Complex tables contain irregular structures and are often used to present a larger, more complex set of data and relationships. They can be difficult for assistive technologies to interpret, and generally slow everyone down. It is best to avoid using complex tables wherever possible. Instead, break them down into smaller, simple tables.

Complex tables are defined as tables that have more than one row header or more than one column header or both. They may also contain cells that span multiple columns or rows.

Tables with these structures are best avoided where possible, as they can be difficult for people using assistive technologies or adaptive strategies to interpret. For example:

  • Screen readers typically read information linearly - from top to bottom, left to right - so when table structure is irregular, it can cause the information to be presented in an order that is incorrect or does not make sense.
  • Additionally, screen reader and browser support for complex table markup varies. This can make navigation of complex tables difficult for people who rely on screen readers and similar assistive technologies.
  • People with low vision who use screen magnification may have difficulty navigating complex tables. They may need to scroll extensively to see sections of the table, and can quickly lose track of their place.

Complex tables can also cause difficulties for users with cognitive disabilities as the complexity of their structure can be difficult to analyze and understand.

Many users may find complex tables overwhelming and may not understand what is being presented visually. They increase cognitive load and generally slow all users down so it is always best to simplify tables wherever possible.

If you must use a complex table, ensure that the correct formatting is used. This helps people who use screen readers and other types of assistive technology. They can navigate complex tables more efficiently and better understand the relationship between the contents of the table’s headers and content cells.

Complex tables can also be difficult for users with cognitive disabilities to understand as the relationship between header and content cell data may be unclear. This includes people with reading difficulties, processing difficulties, limited memory, and limited focus.

Before choosing to use a complex table, follow the guidelines in Data Tables, and decide if your data can be presented in a simple table. If a complex table is necessary there are additional techniques needed to improve the accessibility for all users.

In complex tables, the <thead> and <tbody> elements should be used to ‘group’ data:

  • The <thead> element groups rows that form the column headers of a table
  • The <tbody> element groups rows that form the body of the table
Code example with grouping elements
<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
</tr>
</tbody>
</table>

Tables with header cells that span multiple columns and/or rows are known as irregular tables. If data spans multiple cells, it must be marked up using the <colspan> or <rowspan> attributes.

For example:

  • <td colspan=”2”> would span 2 column cells
  • <td rowspan=”3”> would span 3 row cells

If the span is within the header cells, it should also include the <scope> attribute. This attribute defines the direction of cells covered by the spanned header.

For example:

  • <th colspan=”5” scope=”colgroup”> would span 5 columns and associate all of the data in those columns with the header.
  • <th rowspan=”5” scope=”rowgroup”> would span 5 columns and associate all of the data in those rows with the header.
T-Shirt Availability (Irregular Headers)
ArtistColorSizes available
Patti SmithBlackSmallMediumLarge
WhiteSmallMediumLarge
Fleetwood MacCreamSold out
Code Example
<table>
<caption>
T-Shirt Availability
</caption>
<thead>
<tr>
<th scope="col">Artist</th>
<th scope="col">Color</th>
<th colspan="3" scope="colgroup">Sizes available</th>
</tr>
</thead>
<tbody>
<tr>
<th rowspan="2" scope="rowgroup">Patti Smith</th>
<td>Black</td>
<td>Small</td>
<td>Medium</td>
<td>Large</td>
</tr>
<tr>
<td>White</td>
<td>Small</td>
<td>Medium</td>
<td>Large</td>
</tr>
<tr>
<th scope="row">Fleetwood Mac</th>
<td>Cream</td>
<td colspan="3">Sold out</td>
</tr>
</tbody>
</table>
Example: colgroup, colspan, rowgroup and rowspan attributes

If an irregular header structure is required, follow the W3C documentation for tables with irregular headers.

It is also helpful to include a table summary to help users understand more complex table structures. The summary should include information about the table layout, not the table contents or subject. A simple way of providing a summary is to include it in the table <caption>. That way, it is available to all users. The summary content can be styled with CSS so that it is visually different from the caption.

WNBA Teams - 2022 Season Results:
Column one has the team and games won or lost, other columns show if the game was played at home or away.


Caption HTML Example
<table>
<caption>
<strong>WNBA Teams 2022 Season</strong><br>
Column one has the team and games won or lost, other columns show if the game was played at home or away.
</caption>
...
</table>
Caption Example (with table and code)

For additional methods of providing a summary, refer to the W3C Caption and Summary tutorial.

While it is possible to have tables with multiple levels of header cells associated with each data cell, it is always best to break these tables down into separate, simple tables if possible.

These table structures are too complex to rely on a simple table header <th> and table data <td> cell association. Instead, a unique id attribute is assigned to the <th> cells which is referenced by the corresponding <td> cells using the headers attribute. Each <td> cell can reference multiple table headers.

WNBA Teams - 2022 Season Results
Column one has the team and games won or lost, other columns show if the game was played at home or away

HomeAway
New York Liberty
Games won123
Games lost23
Seattle Storm
Games won115
Games lost13
Code for the first 4 rows
<table>
<caption>
<strong>WNBA Teams 2022 Season</strong><br />
Column one has the team and games won or lost, other columns show if the game was played at home or away
</caption>
<thead>
<tr>
<td class="no-border"></td>
<th scope="col" id="home">Home</th>
<th scope="col" id="away">Away</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="colgroup" colspan="3" id="nyl">New York Liberty</th>
</tr>
<tr>
<th headers="nyl" id="ny-won">Games won</th>
<td headers="nyl home ny-won">12</td>
<td headers="nyl away ny-won">3</td>
</tr>
<tr>
<th headers="nyl" id="ny-lost">Games lost</th>
<td headers="nyl home ny-lost">2</td>
<td headers="nyl away ny-lost">3</td>
</tr>
Example: colgroup and rowgroup attributes

If a multi-level header structure is required, follow the W3C documentation for tables with multi-level headers.

Testing a complex table will require inspecting the HTML code. If you are unfamiliar with how to view the source HTML code, follow the guidance in our Browser Inspect / Dev Tool (Ta11y).

In the code, ensure that:

  • Table and row headers have been defined using <th>
  • Table cells have been defined using <td>
  • Spanned columns have the ‘colspan’ attribute
  • Spanned rows have the ‘rowspan’ attribute
    • Spanned header cells also have the ‘scope’ attribute, with a value of ‘colgroup’ or ‘rowgroup’
  • If an irregular header structure exists, the header and cells have the appropriate ‘headers’ and ‘id’ attributes
  • Content in table headers is meaningful and accurately describes the row or column group that it is associated with.

You can test tables using the Tables bookmarklet, which displays all the markup used in the table on the screen. This can be a much easier way to view the markup than reviewing the source code, especially when it comes to complex tables.

Another useful tool for testing tables is the ANDI bookmarklet. ANDI identifies all table markup and tells you what a screen reader will announce for each table cell as it is selected in the ANDI output. To see this open ANDI, select the Table module and then select the Markup option. For more information on installing and using this tool, see ANDI (Ta11y).

Screenshot of ANDI Table Test Results showing Table Markup added to a table on the web page. Following text provides full description.
Figure 1: ANDI Table Test Results showing Table Markup

In this example from Ta11y.org, markup has been added to each table cell indicating if it is a “th” or “td” cell. The ANDI output for the selected table cell is “Sizes available | Patti Smith | Small” which includes the contents of the column and row headers and the contents of the selected table cell. Note that when navigating through a table with a screen reader only the column header or the row header would be announced, based on the direction of navigation. Both headers would not be announced at the same time.

Listen to your tables with a screen reader.

  • Can you navigate through the table cells correctly?
  • Does the screen reader correctly announce the contents of each cell as you move through the table along with the appropriate table headers?
  • If the table has a caption, is it announced correctly?

If there are problems with the way a screen reader is announcing a table, it may indicate that there is an error in the code. You will need to take another look at the source code to determine the error.