I first blogged about responsive data tables in 2011. When responsive web design was first becoming a thing, there were little hurdles like data tables that had to be jumped. The nature of <table>
elements are that they have something a minimum width depending on the content they contain and that can easily exceed the width of a small screen device.
This image I made then still covers the issue pretty well:

Except… maybe they don’t equally suck. If that image on the left were scrollable, then maybe that’s actually… not so bad. In fact, that’s what I’ve done right here on CSS-Tricks recently. I think it’s the safest way of handling responsive tables when you have no idea what content the table contains. That’s the case here, where I need to set up base table styles that apply to any blog post which may contain a table.
The crux of the idea of a scrollable table is to wrap it in a <div>
that has overflow: auto;
on it. That way the <table>
inside is free to exceed the width of the parent, but it won’t “blow out the width” and instead triggers a scrollbar. This isn’t quite enough though, so here’s Adrian Roselli with the real scoop. The wrapping <div>
needs to be focusable and labelled, so:
<div role="region" aria-labelledby="Caption01" tabindex="0">
<table>
<caption id="Caption01">Appropriate caption</caption>
<!-- ... -->
</table>
</div>
Then apply the scrolling and focus styles, in the condition you’ve done everything else right:
[role="region"][aria-labelledby][tabindex] {
overflow: auto;
}
[role="region"][aria-labelledby][tabindex]:focus {
outline: .1em solid rgba(0,0,0,.1);
}
If you’re going to further engineer responsive tables, there are all sorts of options. One of the classics is to display: block
a lot of the elements, meaning that all the data in a row (<tr>
) ends up as a chunk of stacked content together that stands less of a chance of breaking the parent element’s width. You can get all the data labels properly with pseudo-elements. But, this only makes sense when individual rows of content make perfect sense alone. That’s not the case with every table. A table’s purpose might be cross-referencing data, and in that case, you’ve ruined that with this approach. So again, there are nice approaches for responsive tables when you know exactly the content and purpose of the table. But the best responsive solution when you don’t know is to just make sure they are swipeable.
This is the solution I prefer for most cases. I think the visual cue from the original article is the most important part of this. When I implemented this a while back, I used javascript to handle the visual cues… I think I’m going to have to update it using this pure CSS method.
Yep, that’s pretty much the same thing I did in my site, alright (and the tables there definitely need to stay tables). As long as only the table itself scrolls as opposed to the whole page it should be fine in practice.
The biggest problem is that mobile browsers will refuse to show scrollbars at all costs if you aren’t sliding, which led to somebody not realizing that tables could be scrolled because a column boundary aligned right against the side of the screen. I’ve been thinking about adding arrows to the sides that only show when the table can be scrolled in that direction, but so far no luck with CSS only (every attempt so far seems to be thwarted by one problem), and while I’ve considered javascript to show them (not the scrolling itself of course) this also came up right when Google was considering to make mobile Chrome drop javascript on 2G connections… which wouldn’t have been a big deal except because it shows a warning (no way to mark scripts as safe to drop?) and I didn’t want to risk people I’m doing shady things under the hood because it’s not immediately obvious what went missing.