Redesign a table for Mobile with CSS

So you have a nice looking table in your web application with some rows. And then someone is looking at it on a Mobile device. Now there are two options. You could keep the size of the table, but then the user has to scroll up and down and left to right to view the content. Or you could resize the table, but then it becomes too small and virtually unreadable. Both bad options.

There is a better option using just CSS. Here is the secret on how to do just that.

The normal Table layout

The table could look like this. A header row and some rows with data in it. Looks good, but at some point you can no longer scale it down. From that point on you would need to redisign it by changing the HTML. But that would be hard to maintain. So let's do just that without changing the HTML, with some help of CSS.

Step 1: Break the table

The HTML Table has a few basic elements: Table, TR, TH and TD. These are all inline elements, therefor the Browser will display them next to each other in 1 single line per row. But with some brute force CSS we can put a stop to that. Just add the following in your CSS:

.table, .tr, .th, .td {
  display: block;
  box-sizing: border-box;
}

The display block will force each and every element of the Table to a new line. And now the Table is completely broken:

Step 2: Get rid of the Header

The Header is not really useful anymore. So we can get rid of these TH's using:

.mobileList th {
  display: none;
}

Step 3: Create a fake column with the labels

Now we don't have the Header anymore, it might be hard to understand for the user which value represents what. So we need to add a column in front of them. To do this, I already had my Table cells prepared. This is what a TD looks like:

<td data-col="Name">Brad Wurst</td>

The secret is in the custom attribute data-col. This is what I'm going to use for the fake column. And for the fake column itself I'm going to use the pseudo element "before" from the TD. Here's the CSS:

.td::before {
  content: attr(data-col);
  position: absolute;
  top:0px;
  left: 0px;
  width: 35%;
  padding: 7px;
  background-color: #55AADD;
  border: 1px solid #55AADD;
  color: #FFFFFF;
  font-weight: bold;
  letter-spacing: 1px;
}

The pseudo element will be displayed just before the element itself. There is no text in it, but we can add that using the content attribute. Here I did not put a static text in it, but the value of the attribute data-col. That's why they are their in the HTML of the table. They won't get in the way in the normal view, but they are there to create the fake column.

Step 4: Do some additional styling

Form here on it is just plain CSS styling. And with a bit of positioning it will look like this:

Besides positioning and adding a little margin to seperate the different items, I simulated the alternating rows using the nth-child(odd) and nth-child(even) from CSS:

.tr:nth-child(odd) td {
  background-color: #FAFAFA;
}
.tr:nth-child(odd) td:hover {
  background-color: #DDDDDD;
}
.tr:nth-child(even) td {
  background-color: #EEEEEE;
}
.tr:nth-child(even) td:hover {
  background-color: #DDDDDD;
}

As you can see I did this on the TR because that still is the parent element of the TD's. It's just not where it would normally be, before we broke the table.

It's a wrap!

So this is an easy way to restyle a Table for Mobile without changing the HTML. Ok, you need to prepare the HTML by adding the data-col attribute. But other than that, it's just plain vanilla CSS. To see the result in action I have created a demo page on our website. Click Ctr+U on the demo page to see the HTML source code.

That's it for this post. Feel free to leave a comment or send a question to andre@silveressence.net. Let me know if you got inspired and may the source be with you!