Skip to main content
Andrea Verlicchi

Making the web faster and more user-friendly

Responsive and accessible table design

How to make a potentially wide table fit on small devices, without losing readability and accessibility? Here are simple solutions to make tables look like lists, lists look like tables, in responsive and accessible design.

So let’s say you have an HTML <table> containing some orders, each one having:

  1. a picture
  2. a description
  3. a price

And you need to make it:

Table markup #

Here's the markup of the table you've got.

<table>
  <thead>
    <tr>
      <th scope="col">Photo</th>
      <th scope="col">Description</th>
      <th scope="col">Price</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><img src="https://via.placeholder.com/70x100&text=Product"></td>
      <td>Description</td>
      <td>EUR 12.345</td>
    </tr>
    <tr>
      <td><img src="https://via.placeholder.com/70x100&text=Product"></td>
      <td>Description</td>
      <td>EUR 12.345</td>
    </tr>
  </tbody>
</table>

The solution in this case would be to display: flex the rows, then set their cells direction to vertical using flex-direction: column.

tr {
  display: flex;
  flex-direction: column;
}

@media (min-width: 400px) {
  tr {
    flex-direction: row;
  }
}

And boom. Here's the example on codepen.

But is this really a table? #

Is table the right tag to use here? Is there a chance that we might have used the table tag only for layout simplicity? I mean, isn't it just a list of orders? So why don't use a ul instead?

<ul>
  <li>
    <div class="photo"><img src="https://via.placeholder.com/70x100&text=Product"></div>
    <div class="description">Description</div>
    <div class="price">EUR 12.345</div>
  </li>
  <li>
    <div class="photo"><img src="https://via.placeholder.com/70x100&text=Product"></div>
    <div class="description">Description</div>
    <div class="price">EUR 12.345</div>
  </li>
</ul>

In this case, in the CSS, we just need to make the divs inside the list items to be aligned horizontally, when there's enough space to do this.

@media (min-width: 400px) {
  li {
    display: flex;
  }
}

div {
  padding: 10px;
}

Here's the result:

Accessibility considerations #

The tables can be very accessible if you code them properly, but I think it only makes sense to use tables when the data in each data cell have at least 2 headings: one at the beginning of its column and one at beginning of its row.

If it's only a title per each column you have, and you have a few columns, it's probably better to consider it a list and markup it like a list, using ul or ol as you prefer. Make sure you choose properly!

Last but not least, if you have a non-table markup (ul, div, span) that you are displaying as a table, and you want to make it accessible too, make sure you use ARIA roles to define your rowgroups, your columnheaders and rowheaders, your cells, etc.

Conclusion #

You can use flexbox to easily make a table look like a list, or a list look like a table. Keep accessibility in mind! When coding tables use table headers for rows and columns. When coding pseudo-tables use ARIA roles to define which is what.