Texas Tech University

Making Accessible Tables

Making Accessible Tables on Udemy

Let's talk about tables. If you have a table on your site, it should contain tabular data. Every row in the table should contain data items that relate to the same record, and every column of the table should contain the same type of information. As an example, you may have a table of information about your staff members. Every row would have data related to a single person, and every column would contain the same attribute. So you'd have a column of names, a column of email addresses, a column of job titles, etc. This is the type of data that an HTML table is meant to hold. You should not use a table for layout purposes. You shouldn't use a table if you are using it to have maybe one row of information, the full width, under that maybe three columns of information, maybe the row below that is two columns of information, etc. That's using a table for structure, but the data there isn't organized in rows and columns like we would expect. If you are needing tools for layout, look into Foundation Grid or Flexbox or other tools like that to control how items are arranged on your page.

It's likely that a few cells in your table will give context to the rest of the table. The first row of your table will often contain labels for what data is in their column. These are called column headers, since they give context for what the data is in their column. In some cases, you may want to set the first column of the table to be row headers. This column would provide a label for which row an item in the table is related to. Headers in your table should use the "th" tag, rather than the "td" tag, and should have the appropriate scope value to describe if they are for a row or column.

Let's look at some example tables. In our first example, it might be somewhat hard to see what this table even contains. After a minute, we can see that a couple of categories called "Avengers" and "Justice League" are in this table. Under those cells, we have cells stating first name and last name, and then finally the actual table data or names of members within those groups. Let's hear what this sounds like from a screen reader. [NVDA Screen Reader] Speech mode beeps, speech mode talk. A very bad table heading level 3. Table with 10 rows and 2 columns row 1 column 1 Avengers. Column 2. Row 2 column 1 first name. Column 2 last name. Row 3 column 1 Tony. Column 2 Stark. Row 4 column 1 Steve. Speech mode off. [End NVDA] [Ben] So what did we hear? We didn't get any kind of information about any hierarchy in the table. The blank cell next to "Avengers" was read off as just a blank cell. If this was a very large table, it would be hard to get any meaningful data from this table. It would be hard to understand what the table is even about.

Let's take a look at the next example. The table here has the same data as before, but it's just a little easier to take in the information. The "Avengers" and "Justice League" categories now span two columns, and they're much bigger and bolder than before. We have the same thing with the "First Name" and "Last Name" cells. That's because all of these have been identified as headers to the table and associated with data within the table that they describe. Let's hear what this example sounds like. [NVDA] Speech mode beeps. Speech mode talk. *me adjusting NVDA's focus on the page* A better, but still bad table heading level 3. Table with 10 rows and 2 columns Row 1 column 1 through 2 Avengers. Row 2 Avengers column 1 First name. Avengers column 2 Last name. Row 3 Avengers First name column 1 Tony. Avengers Last name column 2 Stark. Row 4 Avengers First name column 1 Steve. Speech mode off. [End NVDA] [Ben] That sounds a bit better. We now know that Avengers is spanning the whole first row. We also hear the table headers called out alongside the data they describe, which gives us a lot more insight into what the data in the table refers to. Admittedly, doing the table in this way still causes some issues, since we have these two categories represented in the table. It's fairly difficult to assign the table headers appropriately, and in fact this table would be read off incorrectly by a screen reader once you get down to the "Justice League" section.

Here's our next example of the same information, shown a little bit differently again. Now instead of one, somewhat complex table, we have two tables, but are much simpler. We've taken the "Avengers" and "Justice League" headings out of the table and just placed them on the page as headings. The resulting tables now are much simpler, with just the "First Name" and "Last Name" header row, and then the table data itself. Admittedly, there is a bit of white space there between the "Justice League" heading and the bottom of the first table, but a little bit of CSS can tighten that up. Let's hear what this one sounds like. [NVDA] Speech mode beeps, speech mode talk. Two tables are better than one heading level 3. Heading level 4 Avengers. Table with four rows and two columns row 1 column 1 First name, column 2 Last name, row 2 First name column 1 Tony, Last name column 2 Stark. Speech mode off. [End NVDA] [Ben] That sounds a lot nicer to my ear anyway, and would be way easier to navigate.

But let's talk about this data really quick. We started with a somewhat complex structure. We defined the table headers. We split some categories of the table out to make two even simpler tables. But now, our data is just so simple that a bulleted list can effectively hold the information. Let's hear what this sounds like. [NVDA] Speech mode beeps, speech mode talk. Is no table the best table? Heading level 3. Heading level 4 Avengers. List with three items bullet Tony Stark. Bullet Steve Rogers. Bullet Natasha Romanoff. Out of list heading level 4 Justice League. List with three items bullet Clark Kent. Speech mode off. [End NVDA]

This isn't to say that your site can't have tables. It's likely that you may have a lot of information to display, and the best way to do that may be a table. But sometimes it's useful to think about the information you have and how you can simplify those tables to show the data in a way that's just as effective and maybe easier to maintain. Again, we started with this fairly complex table with some subcategories and no headers defined. We started defining the headers of the table. We split out that subcategory. But then in the end, our data was just so simple that a bulleted list can handle it just fine. So think about that with any tables you have. Try to make them simpler. If you think your table is actually two different tables, do those splits on them. And then really think about what's the best way to present that information to your users.