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.

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 & 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.

We need to rethink the approach for responsive

First of all, 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.

Rollover to view animation of these methods:

Squish

1
2
3
4
5
6
7
8
9

Scroll

1
2
3
4
5
6
7
8
9

Collapse rows

1
2
3
4
5
6
7
8
9

Collapse columns

1
2
3
4
5
6
7
8
9

Ways not to build a responsive table

Through trial and experimentation, I discarded the methods which were not optimal for this task, so don't recommend the following:

  1. Generating a second narrower table via JavaScript and hide/show alternately by breakpoint.
    CONS: 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.
    CONS: 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.
    CONS: Not possible to align cells across rows with <tr> type wrappers and display:table-cell overides the flex-item.

Doing it right with FLEXBOX!

  • 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.

  • 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. This is easy to do manually and trivial for a CMS, JS or a framework like React or Angular.

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


Collapse everything with display:block on small screens, now we have RESPONSIVE TABLES!


You can also collapse to Tabs or Accordions

  • Tab and accordion markup sits IN 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.

Other enhancements

So flexy.. you can use the same cell styling for other types of markup, even standard table markup!

Old browsers

Only IE9 and below does not support flex. For older browsers, you can detect flexbox (with Modernizer) and show the mobile version, which is a good example of 'Graceful Degradation'.
eg: .no-flexbox .Rtable > .Rtable-cell { display: block; }


That's IT! 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.


3,758 3 48