Hacker News new | past | comments | ask | show | jobs | submit login
Responsive Tables in Pure CSS (livingsocial.com)
307 points by tvalent2 on April 6, 2015 | hide | past | favorite | 68 comments



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.


While your criticism of losing the ability to easily compare values across columns is valid, that ability is not relevant for many use cases. This use case -- a list of monthly receipts -- is arguably one of those.

Another option here would be to remove less important columns. "Payment #1" seems extraneous. "Period", assuming it is monthly in all cases, could be changed to an abbreviated month name (eg, "Feb"). Now you'd have 3 columns that probably still look okay.

As a general solution for a many-columned table on a small device, I disagree that showing the full table and letting me pinch zoom is a good solution. It's a poor user experience, and I appreciate the designer taking the time to think about what my most important needs are and catering my small screen experience to them.


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

This is exactly why OP's solution to this problem is not universally implemented. It's a good solution in a small set of circumstances, but is a terrible idea if you had good justification for the tabular view in the first place.

This is all well trodden ground in CSS and UX circles. Here's is the same solution (along with several others) from 2011: https://css-tricks.com/responsive-data-tables/

The main takeaway is that small screens just aren't good for certain things, like comparing large data sets.


Totally agree. Why not get rid of some of the extraneous information in the table first? You don’t need MM/DD/YYYY format for every date. You don’t even need the year if you are displaying information for this year, which is probably the most likely in a payments table.

So instead of “02/01/2015" and “01/01/2015 - 01/31/2015” use “2/1” and “1/1-31” … or even “Feb 1” and ”Jan 1-31”.

I assume that under payments they would normally have some other description other than “Payment #1”, “Payment 2”, etc. - otherwise that is a waste of space as well.


Just for the record, the data and arrangement of the data in the blog post is completely contrived.


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


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.


Add it to the list: if you are using a phone you are probably not... shopping, changing settings, signing up, using all the features, comparing products, reading longform, watching a movie, trying to do your job...


My favourite approach is limiting the width of a table to the point where cells are still readable, and having it wider than the viewport width. Then you can easily drag the table left and right.


agree. I would rather pinch zoom so I can compare rows / tables than flip through a bunch of "cards." Must be a Microsoft thing.


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.


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.


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.


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


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.


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


You can apply `position: fixed` to a `thead` element, but you need to either exactly specify or calculate (and recalculate on resize) all of the column widths in pxs.


Hi there, take a look on position: sticky; It does exactly what you want. Please note it is still experimental though.


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.


+1


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.


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.


Absolutely agreed. It works great for this situation.


Chris Coyier - 4 years ago.

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

https://css-tricks.com/responsive-data-tables/


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.


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/

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


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 :)


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


Coyier is always on top of things. His demos have saved me many times.


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.


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

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 but I haven't had a chance to apply it to tables yet


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.


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?


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.


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


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

http://postimg.org/image/qxyl332ef/


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

Demo: 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.


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

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


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.


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


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


Yet gzips into just 100 more bytes.


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


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), so you're allowed to use the technique just as much as they are ;-)


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!


Hiya! What's your jQuery plugin?


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


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


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.


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

Large version: http://i.imgur.com/xrJ4sBt.png


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.


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


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


Why add JS if it isn't necessary?


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!


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.


I don't think there's a reason why he chose to not go with JS, but to show that it's possible with only CSS. IMO I like using less JS because it slows down the Mobile web experience. JS is super powerful and you get to do cool things with it but you always have to keep an eye out for performance.


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


I like the first table better.


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.


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


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


The normal method lacks the responsive features in this implementation.


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


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


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


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.


I think I fault more whoever is voting this into the #1 current story on HN.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: