Accessible, Simple, Responsive Tables

Avatar of Davide Rizzo
Davide Rizzo on (Updated on )

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

There is no single solution to make any <table> appropriately responsive. That’s what I like about this post by Davide Rizzo: it admits that, then gets on with some solutions. This is a great addition to territory we’ve been treading for a while.

Content and Comparison tables

There are many types of tables on websites where content can vary as wildly as the approaches used to make them responsive. The tables I find most frustrating are comparison tables or normal content layout tables, there are really no comprehensive CSS based solutions for making these types of tables responsive.

I set out to find a flexible and simple solution that could work as a reusable web component, regardless of the content within.

Examples of comparison tables

Is table markup still working for us?

Standard table markup seems to make semantic sense and does a pretty decent job of aligning cells. One of my main concerns was accessibility. Surely native table markup helps a user with a screen reader understand the order content should be read in and navigated through?

I did some tests with a simple best practice table. Using a few screen readers (Chrome Vox and VoiceOver), I attempted to navigate the markup:

  1. ChromeVox tells you that you are on a table, while VoiceOver also tells you how many columns and rows the table has (which is helpful).
  2. Neither CromeVox or VoiceOver tells you when you are on a table heading. <thead>, <th> and even scope="row|col" don’t seem to do anything! The only way to get it to recognise a heading is to wrap it in an <h#> tag.
  3. The reader steps through the table via rows no matter how your content is arranged. VoiceOver at least allows you to navigate in any direction using arrow keys, but you still have no indication which order you should navigate in.

In essence, nothing in the markup tells the screen reader user if the content should be read via rows or columns. The most meaningful markup still comes from non-tabular semantic content.

Approaches for Responsive Tables

Let’s think about the different ways a table could behave responsively:

  1. Squash: If columns have little content they might squash horizontally with no issues on a mobile screen so not changing the layout needs to be a valid option.
  2. Vertical scroll: If the layout and content is exact and critical, a user could scroll to the left or right. This is trivial in CSS with an overflow="auto" wrapper.
  3. Collapse by rows: Split each row into its own single column mini-table on small screens. Switching display:table into display:block will cause this with normal table markup.
  4. Collapse by columns: This is where things get tricky. You can’t do this with normal table markup in pure CSS because the code order is by rows and the <tr> wrappers lock it in. We either have to change the markup or start manipulating with JavaScript.
Visual examples of those four possibilities.

Not recommended ways to build a responsive table

Through trial and experimentation, I discarded these methods:

  1. Generating a second narrower table via JavaScript and hide/show alternately by breakpoint.
    Why? Content duplication, no better than an ‘.m’ site. Will break any unique IDs inside a table. Poor idea for Styleguide driven components.
  2. Using normal table markup and JavaScript at a breakpoint to rearrange the table into a responsive version.
    Why? Requires different markup for vertical and horizontal tables. Will break any JS initialisation of table content. Requires lots of JS event listeners and DOM manipulation.
  3. Keeping table markup but switch to display:flex for vertically aligned table content.
    Why? Not possible to align cells across rows with <tr> type wrappers and display: table-cell overrides the flex-item.

Responsive tables with flexbox

1a) For row-oriented tables…

  • Order markup exactly how a mobile or screen reader should read it, use semantic headers and content.
  • Abandon all concept of ‘row’ wrappers.
  • Set the width of each cell as a percentage based on number of columns or rows.
    Auto sizing column widths is not possible.

See the Pen Responsive Tables (By rows) by CSS-Tricks (@css-tricks) on CodePen.

1b) For column-oriented tables…

  • Set the flex order by row to instantly create a vertical table. This must be inline otherwise we would need a unique class for every row. Fairly easy to do manually, or very easy for a CMS or JavaScript to apply.

See the Pen Responsive Tables (By columns) by CSS-Tricks (@css-tricks) on CodePen.

2) Style to help make connections

  • Style cells individually in any pattern you require.
  • Fix cell border duplication with negative margins.

See the Pen Responsive Tables (Cell styles) by Davide Rizzo (@davidelrizzo) on CodePen.

3) Collapse to blocks on small screens

In a small-screen media query, set everything to display: block. That gives us responsive tables!

See the Pen Responsive Tables (Collapse) by CSS-Tricks (@css-tricks) on CodePen.

3b) Collapsing to Tabs or Accordions

  • Tab and accordion markup is inside the table in a logical position
  • Toggle either row or column depending on the cell order
  • Use display: none to toggle for both visual users and screen readers

See the Pen Responsive Tables (Tabs & Accordions) by CSS-Tricks (@css-tricks) on CodePen.

Other enhancements

Align cell content
Add column margins by offsetting cell widths
Zebra stripe the table
Emulate column spans with manual cell widths.
Limitation: There is no way to do rowspans on a flex table.

You can use the same cell styling for other types of markup

Even standard table markup!

See the Pen Responsive Tables (Alternate markup) by CSS-Tricks (@css-tricks) on CodePen.

Fallbacks for no-flexbox

IE9 and below does not support flexbox. For older browsers, you can detect flexbox (with Modernizer) and show the mobile version, which is a good example of graceful degradation.

.no-flexbox .Rtable > .Rtable-cell { 
  display: block; 
}

Conclusion

Overall this method offers so much flexibility that you might consider replacing all your content tables with these techniques. You can continue to add different themes and styles with ease in CSS and designers will be much more effective if they understand upfront what responsive tables are capable of.

Other Responsive Tables Resources


This post was originally published on CodePen.