He has a good point. Data tables can be quite wide, and necessarily so. A single row of data needs to be kept together to make any sense in a table. Tables can flex in width, but they can only get so narrow before they start wrapping cells contents uncomfortably or just plain can't get any narrower.

Responsive design is all about adjusting designs to accommodate screens of different sizes. So what happens when a screen is narrower than the minimum width of a data table? You can zoom out and see the whole table, but the text size will be too small to read. Or you can zoom in to the point of readability, but browsing the table will require both vertical and (sad face) horizontal scrolling.

So here's what we are gonna do...

We're going to use "responsive design" principles (CSS @media queries) to detect if the screen is smaller than the maximum squishitude of our table. If it is, we're going to reformat the table.

The small-screen responsive stuff comes in now. We've already figured out our minimum table width is about 760px so we'll set up our media query to take effect when the narrower than that. Also, we'll target iPads as they are right in that zone.

The biggest change is that we are going to force the table to not behave like a table by setting every table-related element to be block-level. Then by keeping the zebra striping we originally added, it's kind of like each table row becomes a table in itself, but only as wide as the screen. No more horizontal scrolling! Then for each "cell", we'll use CSS generated content (:before) to apply the label, so we know what each bit of data means.

And so, desktops get the regular table experience, mobile (or otherwise small screens) get a reformatted and easier to explore table:

Hey what about IE?

IE 9 and down don't like you setting table elements as display: block; It does weird stuff and doesn't work right. But IE 9 does support media queries. So my solution thus far is just to wrap the media query styles in conditional comments.

If the problem was only that older versions of IE don't support media queries, we could use the css3-mediaqueries-js project (polyfills support for all media queries) or Respond (also polyfill, way smaller, but only does min/max-width). They both work very well. But this isn't our problem in this case.

This all works fine in IE 10 and IE 10 also ignores conditional comments, so the styles will work even if wrapped in !IE conditionals.

See it

There are two pages to the demo, one the responsive table solution, and a link to the non-responsive version so you can jump back and forth to see the problem.

In the demo, I use a couple of extra media queries for mobile to force the body to certain widths so they don't get feisty. View source to snag.

This isn't perfect...

This is just one potential solution to the problem to data tables on small screens. It's not perfect. There may be some accessibility concerns (or maybe not, I'm really not sure). It's likely there are some fancy JavaScript solutions that could approach things differently and also work great. If other solutions to this come along, I'll keep this page updated.

UPDATE: Other ideas

Scott Jehl created two alternative ideas that are both very cool and very different from this. This highlights an important point: it's all about the specific context of your data table that dictates what solution to go with.

One of them makes a pie graph from the data in the chart. On narrower screens, the pie graph shows and the table hides, otherwise only the more information-rich table shows. Arguably, the mobile version is more useful!

The next idea (Scott credits Todd Parker) is to turn the table into a mini graphic of a table on narrow screens, rather than show the whole thing. This shows the user there is a data table here to be seen, but doesn't interfere with the content much. Click the table, get taken to a special screen for viewing the table only, and click to get back.

Tables are/were designed purely for tabular data organized into neat rows and columns. Pages are not nearly as rigid in their design, therefore tables apply rigid layout principles to a flexible design medium and that is a BAD idea.

CSS was designed to style all of the elements in a page, tables included, so its perfect for its intended function.

But in this case, the markup STILL HAS proper table headers, so it’s as accessible as any other data table in any other environment. We’re just hiding the headers in one place and showing them in another without changing markup.

You can try to use “data-” attribute, to which pseudo-elements have access through content declaration:

content: attr(data-something);

Also you can give any table cell headers attribute, which is super semantic and accessible, and use them instead of data. But there is small problem – headers contains values of corresponding headers IDs. I’m not sure, if setting those ID in space separated words would be considered as a good practice (every word would be independent ID and you can pretty fast run out of ideas for different words, cause ID must be unique).

Hey, I am applying this kind of responsive style to magento and I want it to propagate to all of the tables everywhere so I wrote a piece of jQuery code that will fill the data-heading(thats my attribute) with the appropriate info:

From @mathias — We may not need to use “only screen” as part of the media query. This stuff might apply well in other media as well, although I haven’t tested it. I’m more comfortable leaving it as screen only until I can see this being useful ON those other media.

Having worked with data tables in responsive designs before I know they can be a pain.

My concern with this example is that we only see the data table. Reformatting the data to fit onto a narrow screen is great in the context of this example but in the context of an entire site it can consume a lot of space and easily leave a user lost.

Fortunately there is kind of something we can do about this. Admittedly it’s not the best solution but if we want to maintain the horizontal aspect of our data table we can use overflows.

For multi-touch devices such as the iPhone and iPad you can nest your table in a div and set the div overflow to auto. As your flexible site contracts around the table the overflow property generates a scrollbar. Your iPhone or iPad wont display the scrollbar but you can now use 2 fingers to swipe the table left or right in order to display all of the data.

For those devices not fortunate enough to enjoy multi-touch Javascript can be utilized to swipe back and forth with a single touch within this div. Then again this isn’t javascript-tricks.com thus I maintain this is an incomplete solution yet a different angle on the problem.

I don’t know if I agree that this is the most elegant solution. That is a LOT of vertical scrolling just to see a little data with all the visual association of a row gone. I would find that a massive pain to read.

I’ve been pondering this exact dilemma for a project I’m working on recently myself. The solution I settled on was to have a containing div set to overflow scroll. That way there is an easily visible horizontal scrollbar that does not impact the rest of the page but allows the data to retain its formatting.

Speaking as someone who doesn’t do web-dev for a living, and just likes to use proper CSS for my personal-use webpages: regardless of whether or not this is a good solution, it’s frankly awesome you can do it just with CSS.

Spoon! This is a clever way to change to the every growing trend of having to view things in multi viewing formats. Once my local area gets good enough cell signal it will become more important. Yeah there are still areas in the US that do not get 4G. Come visit northern Michigan sometime.

Thanks for insight Chris, always useful. Your solution perfectly viable, pie chart equally as good. What was the other one, ah click to view table page. Could also list the titles and do a press to bring corresponding row of data into view.

It is possible to get the same layout to work even for IE8 and IE9 by adjusting the following within the media query:table, thead, tbody, th, td, tr{
display: block;
width:100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
float:left;
clear:left;
}
and then for each td within the media query setting a height, for example: 40px, and also using respond.js to get media queries to work with IE8 :)

The irony is using hand-coded CSS to specify semantic content in the :before pseudo-elements, in a manner that is incidentally not scriptable and therefore cannot be replicated proceduraly.

But the technique is pretty far sighted as far as the styles go and indicates to a large extent how form-factor-centric data markup needs to be. Ultimately this should be the result of individually selectable views for the data in question: the conversion of table to individually labelled key:value pairs. A structure may be desirable.

On the subject, a friend recently asked me how, as an information designer and front-ender, I would engineer complex automated test reports tables to display well on his smartphone when he was away from work. The answer I gave cited a more granular approach: either offer manual constraints on the scope of displayed data via queries or scripting, or offer a scripted interface which presents a very low resolution display that can be quickly expanded to offer the details of specific entries.

Sometimes the nature of the data, and its meaningfully desirable forms, mean that a small-screen display cannot adequately present it without doing a disservice to the data: sometimes, extra user effort is necessary for the data to retain ostensible relevance.

Nice! Where I work, we struggle with programmatically producing tables for print, often too wide. Something like this might apply for us. Great inspiration. Definitely agree that the format depends on the data and what you know about the reader. For example, in many contexts it would be perfectly understandable to skip the “first name”, “last name” labels, and just put the human-readable name at the top of the cell. Turn it into a kind of card view.

This does not work for me, I have no idea why, spent around 14 hours trying to get it to work, cleared all styles and tried again, again, and again. I am not sure what’s causing weird problems with my tables.

I think the solution is just partway there. Works OK for this table but isn’t as considerate for future dev.
I’d like to see a combination of Derek’s table but with locked headers like we do in Excel, so that the labels stay on the page and only displays one td result at a time. [Or maybe in a combination with Overflow for the results]

Is there a way to have the pseudo-labels only appear for cells that have content? I am doing a simple attendance list and my three columns are Host | Spouse | Guests. To keep the scrolling to a minimum, it would be great if the pseudo-labels did not show unless there is data.

I am pretty new to CSS but my understanding is that there is very little conditional logic that you are able to do within it.

I like how this reformats the table. I have several problems with it. The first is using table tags (I much prefer divs). The second is using this with dynamic pages so that all tables get formatted like this. The third is putting strings into CSS is just horrible for multi-lingual sites.

Has anyone tried using hidden elements for the column titles? Has anyone tried using divs for the structure?

Is there a way to keep the text-wrap working in the td once it switches to smaller screens? I’m getting long text stretching outside the table and a scrollbar after the switch. I’ve tried various word-wrap additions without success.