Fun with tables

By Kathrin

One possible solution for responsive tables:


When it comes to tables there is a history of love and hate. For a long time, tables where incorrectly used to solve layout problems. This was fixed by CSS 2, which introduced several possibilities for creating layouts. After IE caught up on CSS table-display options, tables could finally be used as intended: displaying tabular data in an organized and readable way.

Unfortunately this time of happiness for tables did not last. Now with CSS 3 and responsive design are prevalent, tables are again not flexible enough to serve tiny mobile displays. You can squeeze them down to be very small, but this makes them unreadable in most cases. Additionally, horizontal scrollbars are not the best solution as you loose the ability to quick glance at table content.


Here at DaWanda we’ve had a responsive design since summer 2013. This is our CSS-only solution for displaying tabular data on mobile.

UX perspective Mobile first

From UX perspective we start with the mobile view. The mobile table focuses on giving an overview of each row in turn. The most important information is in the first row and should be self-explaining without a requiring heading. The following rows are have a heading and a value. The last row is for displaying possible actions on the table. They should also be self-explaining without heading.

Desktop view

On the desktop we rotate table 90°. Each mobile table-box becomes one row inside our table. We also have now the typical header row with the title of each column. These are desktop tables everyone is familiar with.

Technical side Markup on mobile

It’s clear to see this is nothing you can achieve with a native table element, because you can not turn a td into a tr. Instead we’re using divs to build our table.

<div class="fake-table-autowidth"> <div class="ft-row"> <div class="ft-cell cell-title"> EBook - my simply + endless summer - XS - XL </div> <div class="ft-cell"> <span class="cell-title visible-xs-inline">Filetype</span> PDF </div> <div class="ft-cell"> <span class="cell-title visible-xs-inline">Filesize</span> 9 MB </div> <div class="ft-cell"> <a href="" target="_blank">schaumzucker</a> </div> <div class="ft-cell"> <span class="cell-title visible-xs-inline">purachsed at</span> 10.05.2014 </div> <div class="ft-cell"> <button class="btn primary">download</button> </div> </div> </div>

We just nest as we would do with a vanilla table. We have one row which contains cells. The titles we show only in mobile have a class which displays them as inline elements.

Additional markup for desktop

For desktop view we have to add the table-headline with the titles. It’s just another row with cells

<div class="ft-row ft-h-row"> <div class="ft-cell ft-h-cell"> Productname </div> <div class="ft-cell ft-h-cell"> Type </div> <div class="ft-cell ft-h-cell"> Filesize </div> <div class="ft-cell ft-h-cell"> Shop </div> <div class="ft-cell ft-h-cell"> Purchased at </div> <div class="ft-cell ft-h-cell"> <span class="text-hide">Download</span> </div> </div>

CSS magic

Now let’s look at the magic part. We start again mobile first

.ft-cell { padding: 5px; } .ft-cell .cell-title { font-weight: bold; } .text-hide { font: ~"0/0" a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } @media (max-width: 768px) { .ft-h-row { display:none; } .ft-cell:nth-child(even) { background-color: #fff; } .ft-cell:nth-child(odd) { background-color: #F8F8F8; } .ft-row { margin-bottom: 1em; } .xs-inline-50 { display: inline-block; width: 49%; } }

We set general styles outside of a media query like font-weight of title elements or padding for the cells. Specific element styles go into our mobile breakpoint media-query which fits to a maximum of 768px. First we hide the table-header row, then we add zebra-colours to each cell. The cells which include a cell-title are set to display:inline-block and width:49% so the title and content are adjacent.

Here is the CSS part of the desktop media-query.

@media (min-width: 768px) { .visible-xs { display: none; } .fake-table { display: table; width: 100%; } .ft-row { display: table-row; } .ft-row:nth-child(even) { background-color: #fff; } .ft-row:nth-child(odd) { background-color: #F8F8F8; } .ft-row.ft-h-row { background-color: grey; border-bottom: 1px solid grey; margin-bottom:0; } .ft-cell { display: table-cell; vertical-align: middle; padding-left: 5px; padding-right: 5px; } .ft-cell.ft-h-cell { font-weight: bold; } }

We hide the inside title selected by the class visible-xs and build up our CSS table. we add also zebra-colours to the row and set the font-weight of our heading cells to bold.


Here you can find a demo of the table. This solution is lightweight and straightforward. We do not have to duplicate the content, only additional header titles if they’re needed to understand the content. Our solution of course has some negative aspects. It loses the semantics associated with the table elemen and it still needs some duplication. Additionally, tables with many rows occupy a lot of space on mobile. This could be solved by toggling the table contents so that you only see the first column of each, row and on expand you would show the hidden content.

Originally published at on March 17, 2015.