Responsive Tables Done Right

Tackling the challenge of forcing a table to behave with a responsive design.

Ian Svoboda
The Code Dojo

--

View Demo: http://codepen.io/Akthalian/full/rlHGB/

Works with: IE9 +, Chrome, Safari, Opera (9.x+ )

One of the trickiest parts of designing a responsive site involves deciding how you handle tables. At a certain point, it becomes impractical to just shrink the width of the table as the device width shrinks. Often this is because the content being displayed becomes eligible. Tables don’t behave with the flexibility of other elements by default and do require some overrides.

The goal of this post is to provide inspiration for how to create a responsive table. This guide assumes you are familiar with CSS and responsive design practices.

Our desired outcome is to create a responsive table with pure HTML/CSS. One important note: some of the selectors in use here will not be compatible with IE8. This is ultimately irrelevant, since 1. IE8 doesn't support media queries and 2. IE8 isn't used in a mobile/small screen environment.

The HTML

To get started, we’ll create a basic four column table, using some standard markup. The only thing we’ll add in to make things simpler is a title attribute. This will allow us to easily create the labels when the table responds to a different layout. This also serves to remind the user what information they’re looking at if they hover over the cell with their cursor.

<table class="res-table" cellspacing="0">
<tbody>
<tr class="row header">
<th>Name</th>
<th>Favorite Movie</th>
<th>Birthday</th>
<th>Favorite Holiday</th>
</tr>
<tr class="row">
<td title="Name">Ian</td>
<td title="Favorite Movie">Star Wars</td>
<td title="Birthday">2/16/89</td>
<td title="Favorite Holiday">Christmas</td>
</tr>
<tr class="row">
<td title="Name">Tim</td>
<td title="Favorite Movie">Indiana Jones</td>
<td title="Birthday">1/27/78</td>
<td title="Favorite Holiday">Easter</td>
</tr>
<tr class="row">
<td title="Name">Andy</td>
<td title="Favorite Movie">Inception</td>
<td title="Birthday">8/2/81</td>
<td title="Favorite Holiday">Halloween</td>
</tr>
<tr class="row">
<td title="Name">Lincoln</td>
<td title="Favorite Movie">The Island</td>
<td title="Birthday">6/29/75</td>
<td title="Favorite Holiday">Thanksgiving</td>
</tr>
</tbody>
</table>

The CSS

Since we've already specified the title attribute for our cells, we can use the content property to pull this in for the labels when the page resizes to something smaller than 768px (48em, 16px font-size). The CSS below creates some basic styling for the table in our example.

/* Base Styles */
* {font-family: Helvetica;}
.centered {text-align: center;}
/* Begin Responsive Table Styling */
.res-table,
.res-table * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.res-table {
width: 90%;
margin: 1em auto;
}
.res-table td {
text-align: center;
border: 1px solid #222;
margin: 0;
padding: .5em;
}
.res-table th {
background: #222;
color: #FFF;
text-align: center;
padding: .5em;
}
.row:nth-of-type(even) td {
background: #E3263A;
color: #FFF;
}

Now, we need to add some CSS to make the table actually respond. The principle is just to reset the display property of the table elements to blocks, so they stack on top of each other. From there, we just use the :before pseudo element to display the labels for each of the cells. This involves the use of the content property to display the “title” attribute as the text for the new label. I personally prefer this method since it retains a familiar structure and helps make the data inside the table easy to identify for the viewer.

/* Media Queries for less than 768px (assumes 16px width) */
@media screen and (max-width: 48em) {
.res-table tr,
.res-table td,
.res-table tbody {
display: block;
width: 100%;
}
.res-table td {
position: relative; /*necessary to position the :before element*/
padding: 3em 0 1em 0; /* Creates room for responsive label*/
}
.res-table th {
display: none; /*Hides regular headers*/
}
.res-table td:before {
content: attr(title); /*Inserts the text for the label*/
background: #222;
color: #FFF;
padding: .5em;
position: absolute;
top: 0;
left: 0;
}
}

And now you have a responsive table! Again, this example will not work in IE8 by default since that browser lacks support for media queries, however the technique used here has universal support in modern browsers.

I hope you've enjoyed this article. If you have any questions or feedback, feel free to tweet me @iansvo.

--

--

Ian Svoboda
The Code Dojo

Web Developer, Consultant, and Strategist. I love designing interactions, writing elegant code, and working on a great project.