In HTML (and in general), you use tables to organize related data. For instance, you can use a table to organize a recipe, such as ingredients, quantity, and measurement units. You can also use a table to compare train tickets.
You can create a table in HTML with table
and its associated tags ( th
, td
, tr
, etc.).
Although this method has mostly disappeared from websites, it is still used to structure emails.
Don't be surprised if you see the table tag in the source code of your emails. Email clients, both software (Thunderbird, Mail) and those using a web interface (Gmail), are not standardized. So sometimes, they rely on the table
and related tags to design them.
Luckily, there are excellent libraries (like Mjml) to help you do the job without relying on tables. 😉
In this chapter, you will:
Create a table correctly and learn the impact that poorly constructed ones have on accessibility.
Develop a table correctly by associating column and row headers with table content.
Manage complex table structure accessibly.
Analyze a Bad Example of a Table
To begin this section, let's start with an example of a table taken from a cooking recipe site.
Below is the source code of this table, which does not follow good practices:
<!-- Bad example of a table -->
<div>
<div>
Ingredients for 4 people
</div>
<div>
<div></div>
<div>
<div>
1 tablespoon
</div>
<div>
garlic
</div>
</div>
<div></div>
<div>
<div>
2 tablespoons
</div>
<div>
cream
</div>
</div>
<div></div>
<div>
<div>
4 pieces
</div>
<div>
chicken thigh
</div>
</div>
</div>
</div>
As you can see, it consists of div
tags, which have no semantic meaning.
So what are the consequences of these kinds of tables for accessibility?
This table provides no information about the content type included within it. Assistive technology users won’t even know they’re interacting with a table.
It gives no information about how the elements relate to each other.
Although less and less common (as developers are becoming more informed about accessibility), you still find these types of tables on the web, especially in some libraries.
Create an Accessible Table
Now that you have seen what not to do when you want to create tables, let's look at good practices!
Add Basic Table Structure
Let's start from this table and make it more accessible.
<table>
<caption>Passengers of flight 377</caption>
<thead> <!-- Table header -->
<tr>
<th>Name</th>
<th>Age</th>
<th>Country</th>
</tr>
</thead>
<tfoot> <!-- Table footer -->
<tr>
<th>Name</th>
<th>Age</th>
<th>Country</th>
</tr>
</tfoot>
<tbody> <!-- Table body -->
<tr>
<td>Carmen</td>
<td>33</td>
<td>Spain</td>
</tr>
<tr>
<td>Michelle</td>
<td>26</td>
<td>USA</td>
</tr>
<tr>
<td>Francis</td>
<td>43</td>
<td>France</td>
</tr>
<tr>
<td>Martine</td>
<td>34</td>
<td>France</td>
</tr>
<tr>
<td>Jonathan</td>
<td>13</td>
<td>Australia</td>
</tr>
<tr>
<td>Xu</td>
<td>19</td>
<td>China</td>
</tr>
</tbody>
</table>
The table uses table
and associated tags to give the information structure. It differentiates between headers and content cells by using th
and td
. Notice that there are two different types of headers: row and column. We’ll come back to this in the next section. Finally, it includes a caption tag to give it a description.
Enrich Your Table With Attributes
In addition to standard table tags, also add the scope attribute to the th
cells to improve accessibility.
The scope
attribute makes it possible to define whether a header defines a row or a column.
scope="col"
indicates that a cell is a column header.scope="row"
indicates that a cell is a row header.
Some tables will include a combination of both row and column headers.
<table>
<caption>Passengers of flight 377</caption>
<thead> <!-- Table header -->
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
<th scope="col">Country</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Carmen</th>
<td>33</td>
<td>Spain</td>
</tr>
<!-- Remaining content of the table -->
</tbody>
</table>
Now the table uses the scope attributes to indicate which cells a particular header refers to. Without this attribute, assistive technologies assume that a th
cell refers to a column, so a scope attribute is essential if your table includes row headers.
Discover Accessibility for Complex Tables
Now that you know how to make a simple table accessible, let’s focus on complex ones. A complex table contains cells that span more than a single column or row, which typically nests and organizes information.
Here is an example of a table that organizes data in a more complex manner.
<table>
<caption>Sales and purchases - 2019</caption>
<col>
<colgroup span="2"></colgroup>
<colgroup span="2"></colgroup>
<tr>
<td rowspan="2"></td>
<th colspan="2" scope="colgroup">January</th>
<th colspan="2" scope="colgroup">February</th>
</tr>
<tr>
<th scope="col">Purchase</th>
<th scope="col">Sale</th>
<th scope="col">Purchase</th>
<th scope="col">Sale</th>
</tr>
<tr>
<th scope="row">Thomas</th>
<td>50.000</td>
<td>30.000</td>
<td>100.000</td>
<td>80.000</td>
</tr>
<tr>
<th scope="row">Alexandra</th>
<td>10.000</td>
<td>5.000</td>
<td>12.000</td>
<td>9.000</td>
</tr>
</table>
In the example above,
The
colgroup
tags, used with thecol
tag, allow you to define a group of columns within a table.Indicate which cells a header cell refers to by adding the
scope = colgroup
attribute.
Try to keep the design of your tables as simple as possible. They will require less coding work and will be more easily understood by your users.
Tonight in Gotham: Make an Accessible Schedule Table
Let's go back to our “Tonight in Gotham” project and open the weekly-schedule.html
file. This file contains the table in our Figma mockups.
As you can see, we have a rather complex table; a schedule that includes information organized vertically (day of the week) and horizontally (time of day).
To indicate which header cells refer to which content cells, you need to use the scopeattribute:scope="row"
and scope="col"
.
For grouped boxes (i.e., the "Lunch" box or the "Rock climbing" box), we’ll use the column and row attributes: colspan
and rowspan
. These increase the number of cells horizontally and vertically, respectively.
We could go even further. If you run this page using a validator (which we'll discuss in Part 2 Chapter 5), you’ll see a warning related to the table. The validator asks you to fill in the headers
and id
attributes. You can fill them along with the scope ones to improve the likelihood that assistive technologies will correctly read the table.
Finally, you can also use the caption
tag to describe your table. This is only displayed for screen readers (we use the sr-only
CSS class to hide the text from users).
Let’s Recap!
Avoid using nested
div
s when you create a table. Semantically correcttable
and associated tags are necessary for accessibility.Consider using a
caption
tag to define the meaning and purpose of the table.The
scope
attribute allows you to associate table headers with content cells.
In the next chapter, we are going to see how to make your audio and video content accessible. See you soon!