The code for this article is based on the work of Adrian Roselli and Chris Coyier in their posts entitled Responsive Accessible Table and Responsive Data Tables.
You can view the code on GitHub and check the demo online.
Introduction
Tables are used to present data in a tabular format. In this article you will learn how to create a table that's not only accessible but also responsive.
Responsive Table
Responsive Web Design came around in 2010, but HTML tables did not play nicely with it. In 2011, CSS-Tricks wrote a post about responsive data tables which works without JavaScript and not sacrificing accessibility.
Fast-forward to 2017, Adrian Roselli wrote a detailed post on how to create responsive and accessible table but it uses JavaScript to make it work well on mobile. Without JavaScript, the table occupies half of the screen width on a mobile viewport.
I could not find a way to fix this but I realized that I could combine both techniques into one.
Responsive and Accessible Table with or without JavaScript
The trick is to combine Chris and Adrian's technique. Chris' technique will be the default because it works without JavaScript and when the browser interprets JavaScript we change to Adrian's technique.
The HTML table has a CSS class noJS-version
. This class and its related selectors is the CSS code for the responsive table by Chris. You can check the code in index.html
but here is part of it:
<!-- Code truncated to save space -->
<div role="region" aria-labelledby="tableCaption" tabindex="0">
<table id="worldLeaders" class="noJS-version">
<!-- Table data -->
</table>
</div>
When JavaScript is available, noJS-verion
is changed to js-version
which (and its related properties) contains code for the responsive table by Adrian.
The following JavaScript does the trick:
// Grab the table
let table = document.getElementById("worldLeaders");
// Remove the non JavaScript version by Chris
table.classList.remove("noJS-version");
// Add the JavaScript version by Adrian
table.classList.add("js-version");
Adrian also provides the function AddTableARIA
which (as it name implies) adds ARIA attribute to the table.
With this you have two versions of the table, available to users with or without JavaScript and also accessible.
Screen Reader testing
There are various screen readers out there, for this article, NVDA was used in testing and the results were welcoming.
Screen Reader testing: Without JavaScript
Without JavaScript, after reading the data before the table (the page metadata and page heading), NVDA recites the table has having 6 rows and 3 columns then proceeds to read the table data.
Even on mobile viewport when the first row is not visible it is still available to screen readers because it's only moved off-screen with the following code:
@media only screen and (max-width: 760px),
(min-width: 768px) and (max-width: 1024px) {
/* Hide table headers (but not display: none;, for accessibility) */
tr:first-of-type {
position: absolute;
top: -9999px;
left: -9999px;
}
}
Here is a partial "transcript" of the page with JavaScript disabled and on a Desktop viewport:
Responsive Accessible Table
Main Landmark heading level 1 Responsive and Accessible Table that works without JavaScript
Region table with 6 rows and 3 columns caption World Leaders and their Currencies
Row1 Column1 Name
Column2 Country
Column3 Currency
Row2 Name Column1 Boris Johnson
Country Column2 Britain
Currency Column3 Pound
Row3 Name Column1 Donald Trump
Country Column2 U.S.A.
Currency Column3 Dollar
On a mobile viewport, NVDA recites the table differently due to the modifications made to the table for it to occupy the viewport:
Row1 Column1 Name
Column2 Country
Column3 Currency
Row2 Column1 Name Boris Johnson
Column2 Country Britain
Column3 Currency Pound
Row3 Column1 Name Donald Trump
Column2 Country U.S.A.
Column3 Currency Dollar
The main difference is that the screen reader reads the column number before the column data as it's seen on screen.
Screen Reader testing: With JavaScript
With JavaScript, after reading the data before the table (the page metadata and page heading), NVDA recites the table has having 6 rows and 3 columns.
Here is a partial "transcript" of the page with JavaScript enabled and when the table is viewed on a Desktop device:
Responsive Accessible Table
Main Landmark heading level 1 Responsive and Accessible Table that works without JavaScript
Region table with 6 rows and 3 columns caption World Leaders and their Currencies
Row 1 Column1 Name
Column2 Country
Column3 Currency
Row 2 Name Column1 Boris Johnson
Country Column2 Britain
Currency Column3 Pound
Row 3 Name Column1 Donald Trump
Country Column2 U.S.A.
Currency Column3 Dollar
On a mobile viewport, NVDA reads the table has having 5 rows and 3 columns. The reason for the variation of row number is that the first row is hidden using display: none
.
The code below hides it therefore, it's not available to screen readers:
@media screen and (max-width: 37em), print and (max-width: 5in) {
.js-version th,
.js-version tr:first-of-type {
display: none;
}
}
The ResponsiveCellHeaders
function does a lot of heavy lifting to make the table accessible on a mobile viewport.
In addition, the tabular data is read differently due to the rearrangement and modification of the table to fit the mobile viewport:
Row 1 column 1 Name Boris Johnson
Column 2 Country Britain
Column 3 Currency Pound
Row 2 Column 1 Name Donald Trump
Column 2 Country U.S.A.
Column 3 Currency Dollar
The main difference is that the screen reader reads the column number before the column data as it's seen on screen.
Conclusion
In this article you've learned how to create a responsive and accessible data table but you'll have to do more work with the arrangement on mobile viewport when the table is complex than what's shown here.
Did you find a typo or an error? Let me know in the comments. Thank you.