
Responsive Tables in Pure CSS - tvalent2
https://techblog.livingsocial.com/blog/2015/04/06/responsive-tables-in-pure-css/
======
sixQuarks
Changing the table format from rows to "cards" is an ABSOLUTELY TERRIBLE
solution. I don't understand why people do this. It's not a table anymore. You
can't easily compare the figures in the columns against each other.

The optimal solution, in my opinion, would be if you could specify a viewport
width within a section of the site. The browser would then shrink that portion
down and the user would see the full table, shrunk down to the width of the
browser. The user can then magnify that area to see the data better.

Not sure if I'm making sense here. Also, I don't think this is technically
possible right now.

~~~
fiatjaf
If you are using a phone you are probably not doing some heavy math with row
comparisons.

~~~
teraflop
It's not about "heavy math." On a small-screened device like a phone,
information density is _more_ important, not less. This change dramatically
reduces the density, so you have to do much more scrolling to see the same
amount of information.

------
im2w1l
The article doesn't explain all tricks they use. A media query is used to
apply the stylesheet selectively to small window sizes. That stylesheet splits
the table into multiple ones.

The original table's border is removed, and every tr is styled to look like a
table by giving it a border. tds are turned into rows by setting
display:block. The td rows are given row headers using pseudo elements, which
pulls their content from an attribute on the corresponding td.

~~~
wallawe
Yeah, I wanted to focus on using pseudo elements to pull content in from data-
attrs but obviously I could/should have gone into more detail on the other
bits and pieces. Thanks for the suggestion.

------
JoshTriplett
This seems like an impressive approach for data that uses a table for grouping
but remains understandable when grouped linearly with duplicated labels.

However, for tables showing genuinely tabular data, I'd almost always prefer
to just see the original table and scroll horizontally, perhaps with
appropriate heading columns or rows fixed so that they always display.

Does anyone have appropriate CSS that produces an effect similar to "position:
fixed" but _only_ for horizontal scrolling, not for vertical scrolling? Or
only for vertical scrolling, with it scrolling off the screen when scrolling
away the last row of the table?

Imagine the following as a large table:

    
    
             | col1 | col2 | col3
        row1 |  d11 |  d12 |  d13
        row2 |  d21 |  d22 |  d23
        row3 |  d31 |  d32 |  d33
    

Scrolling horizontally should keep the row labels visible, and scrolling
vertically should leave the column labels visible until the last data row is
scrolled off the screen. And ideally that should not require _any_ JavaScript.

~~~
kolme
Yes, it can be easily done with a combination of divs, fixed width and
overflow-x: scroll.

But I doubt one can do that with a table only, which is a shame, because it
would lose markup semantic.

Edit: Little PoC
[http://codepen.io/anon/pen/LEoyrK](http://codepen.io/anon/pen/LEoyrK)

~~~
91bananas
Nearly every solution for this I have seen or implemented uses a combination
of 2 divs with tables inside to work the scrolling. Tables just aren't built
to do that well in my opinion.

~~~
Silhouette
_Nearly every solution for this I have seen or implemented uses a combination
of 2 divs with tables inside to work the scrolling._

Yes, we use a variation of that theme as well.

It works to a useful degree, as long as you have enough control over the
dimensions that you don't wind up with the row heights differing between the
row headers table and the data rows table.

Of course the mark-up is semantically poor, but then HTML's enforced columns-
inside-rows nesting for tables is already horrible to work with if you want to
show a data record per column and use the row labels for the fields rather
than vice versa, making any sort of templating system fragile as well. Rather
like floats, this is one of those areas where no amount of CSS tweaks can now
make up for underlying weaknesses in the spec of HTML itself.

 _Tables just aren 't built to do that well in my opinion._

We could do better than what we have, though. Hopefully we will before too
long, if position:sticky becomes standardised, complete with the notes about
making it work properly in a tabular context where some other positioning
explicitly isn't required to.

I'm not sure how effectively we'll be able to write a comprehensive polyfill
without resorting to JS, so maybe we'll have to settle for gracefully
degrading to having the entire table scroll without locking the row headers in
place. At least the table mark-up will be more sensible than having two
completely separate table elements with some sort of wrapper(s).

------
spdustin
I do this in my SharePoint responsive design classes. Students are taught how
to make a custom table for a list view to include the data-attributes
necessary to render field names at different breakpoints as well as data-
attributes to set which breakpoints the fields should be visible. It's only
one possible solution, as you've found (and others have mentioned), and I do
show others (like overflow-x: scroll and such).

Data tables are hard in a corporate setting when mobile access is thrown in.
It takes a lot of planning to determine the actual needs of users whose usage
context puts them on a mobile phone or a tablet. Mobile <> in motion, and
tablet <> on a couch. Oil rig operators may use a tablet to access production
data, and so their tables would need larger targets for scrolling or toggling
columns, and a larger/heavier font with higher contrast colors to be visible
in harsh lighting conditions. Field sales reps may be using their phone while
in the lobby before a sales meeting, and don't necessarily need just a subset
of data.

Content may be king, but context is its queen.

~~~
tzm
+1

------
criswell
Our users never seem to like this approach. It does not work very well at all
with complex tables (colspans, rowspans), sorting and filtering feels funky if
you don't know it's a table from the start and it's insanely repetitive. Most
of the time we end up wrapping the `table` in a div with `overflow: auto` and
then they can scroll around the table. The only issue is when a column ends at
the edge of the screen so a user doesn't know to scroll. What we did to help
with this is put a shadow on the edges in the directions you can scroll.

~~~
wallawe
It's definitely not for every scenario. It will depend on your data, whether
or not you need sorting as you mentioned, and how many total rows there are in
the table (card effect becomes too much after 20 or so). However for this
simple use case, we thought it the best way to go.

~~~
criswell
Absolutely agreed. It works great for this situation.

------
at-fates-hands
Chris Coyier - 4 years ago.

He did this and added some reader submissions on other approaches.

[https://css-tricks.com/responsive-data-tables/](https://css-
tricks.com/responsive-data-tables/)

~~~
wallawe
I linked to that post in the in the article and mentioned the reasons it was
slightly different but built upon that idea. He throws his content in the
stylesheets.

~~~
JangoSteve
Yup, though the different way to do it with data- attributes and no content in
the stylesheet was also written about here [1] in 2012, and demo'd here [2] at
the bottom of the page in the "No more tables" example.

We've been using this same technique in several projects where it seemed
appropriate for the past few years and have been loving it.

[1] [https://css-tricks.com/responsive-data-table-roundup/](https://css-
tricks.com/responsive-data-table-roundup/)

[2] [http://elvery.net/demo/responsive-tables/#no-more-
tables](http://elvery.net/demo/responsive-tables/#no-more-tables)

~~~
wallawe
Yeah, I presumed I wasn't the first under the sun to do it; just thought it
would be interesting to write about since some of my fellow front-enders
hadn't seen the technique and google didn't turn up either of those links :)

~~~
JangoSteve
And those links weren't very descriptive and didn't fully explain the
technique, so definitely helps to add to the ecosystem.

------
antidaily
I used this technique on a project recently and in the end, we collectively
determined that we didnt really even need the labels if the column info was
thoughtout enough. So my advice is, make sure you need the labels before you
automatically take this route. Order #, Item, Price type stuff can be pretty
self-explanatory.

------
err4nt
This is similar to the solution I came up with for a Fantasy Sports web app
that needed responsive tables, check out the table class demo page:
[http://ballr.com/new_design/tables](http://ballr.com/new_design/tables)

The problem was that there is no way to reliably have the responsive styles
kick in with CSS alone. You need to know how wide that table is on the page to
know when it needs to respond. At his shortfall of CSS (and others) has driven
me to create a CSS polyfill to add Element Query support to CSS so I finally
can build tables that are responsive wherever they display. My plugin is
available at [http://elementqueries.com](http://elementqueries.com) but I
haven't had a chance to apply it to tables yet

------
halosghost
Interesting! The author should consider using the ISO 8601 recommended date
format though (`%F` in `date`). It doesn't completely remove the ambiguity,
but the standardization helps to avoid it.

------
nerdy
First a disclaimer: I am a programmer, not a designer or UX specialist.

When I make a responsive table I feel like turning every column into a
distinct row makes it _more_ difficult to navigate; instead I prefer to split
the columns into groups and wrap them with alternate coloring. So if there are
5 columns maybe 3 go in the top of the row and 2 go in the bottom of the row
(top and bottom sharing the same background color).

Is this kind of cols-to-rows substitution more user-friendly?

~~~
jonahx
An example would help answer definitively, but based on that description I
don't think most people would find it intuitive. At a glance, it probably has
a janky feel too. But I could be wrong.

------
jefurii
I know it's not _cool_ to use tables, but this is a table of numbers. Tables
were designed for this.

------
kevinrpope
Nothing shows on IE11 on Win7. Also the header image has a horizontal scroll
bar.

[http://postimg.org/image/qxyl332ef/](http://postimg.org/image/qxyl332ef/)

------
eneveu
Reminds me of a project I stumbled upon while researching responsive table
patterns a few months ago:
[https://github.com/filamentgroup/tablesaw](https://github.com/filamentgroup/tablesaw)

Demo:
[http://filamentgroup.github.io/tablesaw/demo/stack.html](http://filamentgroup.github.io/tablesaw/demo/stack.html)

We didn't have the time to implement this in our app, but it looked great. I'd
like to see how easy it is to integrate to use Bootstrap styles.

------
frequent
Very similar to jQuery Mobile reflow table (uses some JS)

[https://api.jquerymobile.com/table-
reflow/](https://api.jquerymobile.com/table-reflow/)

A while ago, I css-ed a table into a list for small displays, because lists
seem "natural" to me on mobile than any crammed table. Not perfect but been
using it ever since:

[http://jsbin.com/wisaxawozaqa/1/watch?html,output](http://jsbin.com/wisaxawozaqa/1/watch?html,output)

------
some1else
This indeed transforms information about a group of records from a tabular
spreadsheet into individual card representations.

The people who are pointing out that this solution isn't "a more powerful
responsive label scrolling spreadsheet" are right, but they're likely only
after a faster horse.

As an aside, a table can have multiple tbodies according to HTML specs, so
there's no need to use CSS generated elements to achieve the card styling in
the demo. Just wrap each record into a tbody and style that.

~~~
usaphp
So if you have say 100+ records in a table you will end up with 100+ extra
<tbody> and </tbody> tags? Just to style it for mobile? I don't think its a
good solution

~~~
joesb
The same can be said about adding anything to repeated items.

------
franciscop
This solution is pure love! Any idea about the license? It doesn't appear to
say anywhere and I would love to add it to Picnic CSS as a plugin (developer
here).

~~~
JangoSteve
They didn't publish any code that is non-trivial to implement (and all but 1
line of code is specific to their actual data and styling), so there wouldn't
be any license to worry about. This technique has also been published before
([http://elvery.net/demo/responsive-tables/#no-more-
tables](http://elvery.net/demo/responsive-tables/#no-more-tables)), so you're
allowed to use the technique just as much as they are ;-)

------
freshyill
This is a great approach for when you have complete control over your markup.
If it's user-generated (like a table in the body of a post in a CMS, for
example), it gets trickier.

I have a tiny jQuery plugin to stick a span inside a cell to form the heading
at small sizes, but I like the data-attribute approach better. I think I'll
change my plugin to do it this way now.

Related: Hey Travis and Will, nice work on this!

~~~
tvalent2
Hiya! What's your jQuery plugin?

~~~
freshyill
Right here. Like I said, it's super basic.
[https://github.com/freshyill/Responsive-Table-
Helper](https://github.com/freshyill/Responsive-Table-Helper)

------
ctingom
There's an excellent plugin for WordPress called FooTable that works in
conjunction with TablePress that does something similar.

~~~
snowwrestler
FooTable has my favorite implementation of this idea. It still looks like a
table, but with fewer columns. Each row gets a big [+] to expand down to show
the "hidden" values with their column headers as key-value pairs.

The best part is that I can choose which columns "hide" in whatever order I
want, for however many breakpoints I want.

------
telekid
We've been using a similar technique over at untapt for a small table that
display's past job applications:

Small version:
[http://i.imgur.com/sJOxCQw.png](http://i.imgur.com/sJOxCQw.png)

Large version:
[http://i.imgur.com/xrJ4sBt.png](http://i.imgur.com/xrJ4sBt.png)

------
ahsteele
The CSS Values and Units Module Level 3 details that the `attr()` function is
at risk of being dropped during the CR period: [http://dev.w3.org/csswg/css-
values-3/#funcdef-attr](http://dev.w3.org/csswg/css-values-3/#funcdef-attr).

~~~
acdha
Is that `attr()` at all or just the expanded version which allows different
units and fallbacks?

[https://developer.mozilla.org/en-
US/docs/Web/CSS/attr#Browse...](https://developer.mozilla.org/en-
US/docs/Web/CSS/attr#Browser_compatibility) goes back far enough that I'd be
surprised if they'd drop a feature which has been around for such a long
period of time or that the browsers vendors would do anything other than
ignore the spec until it was corrected.

------
dfar1
Interesting read, but why no JS? Don't all mobile devices play well with JS?
Is it a file size issue?

~~~
freshyill
Why add JS if it isn't necessary?

~~~
Domenic_S
That's a pretty trite response. I can think of a few reasons:

1) Maintainability. JS is probably easier to grok in some circumstances, ie.
you don't have to send new devs to a blog post to explain the CSS on your
project.

2) Cost/benefit analysis of dev time, ie. you could do X (where X is some
minor display that 1% of your users see) in pure CSS in 12 hours, or do the
same in 30 min of JS.

3) Cost/benefit analysis of page size, ie. you can do in 4 lines of JS what
would take 400 lines of CSS. Sometimes a few lines of jQuery obviates several
hundred lines of CSS (between the media queries, browser-specific overrides,
and so forth).

The interesting question the article should address was why the CSS solution
was a better choice than the JS solution. I have a gut feeling the answer is
way better than "we just wanted CSS only for purity's sake", and personally
I'm interested in knowing what that answer is!

~~~
UUMMUU
Well the thing is, none of your reasons are applicable here. He has a valid
question as to why you would need JS as this is purely a styling between
mobile and desktop. The only thing you could potentially do with JS would be
to strip the content and rerender it which would be very strongly tied to the
HTML structure. Once again, your points are valid, mostly, but for this
particular problem, you wouldn't need or even want to do it via JS. I think
that's the solution to the original question.

------
danellis
You'd think an article about responsive CSS would be readable on a mobile
screen.

------
dalacv
I like the first table better.

------
bgarbiak
It's not "pure CSS" if it's using data-attributes. It's CSS _and HTML_. With
an access to both of these it's a trivial job. It would be sensational if
someone would find a solution for that without using the latter (or JS, or
server side processing) - for example: for the user generated content.

My joke-solution (working only for fixed amount of rows, with fixed
dimensions): multiplying the headers for each row with _text-shadow_.

------
fredkelly
We ended up prepending column labels to each row in order to get the Bitnami
pricing page [1] to work on mobile. Similar to this case it works for a small
dataset, but I don't creating a 'card' for each row in a >10 row table is ever
going to produce a good experience.

[1] [https://bitnami.com/cloud/pricing](https://bitnami.com/cloud/pricing)

------
cms07
I hate it when web developers do things like this. The normal version of
things is almost always better it seems.

~~~
psychometry
The normal method lacks the responsive features in this implementation.

~~~
cms07
That's exactly what I don't like about it.

~~~
psychometry
You don't want your websites to be responsive? OK, well I'm hoping IE6 still
runs on your computer/phone.

------
fourstar
A media query? Dang Living Social tearing up the engineering scene over here.

~~~
Raphmedia
You missed the points.

He is using attr(data-label); to pull the titles from the data attributes and
then uses Pseudo Elements to add the title to each td while displaying them in
blocks. The end effect is very nice and requires no JS.

