How to create a Responsive and Accessible data table

Habdul Hazeez - Nov 13 '20 - - Dev Community

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>
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .