Skip to main content

Tailwind Responsive Table

No custom styles required; Also yes, it collapses on mobile ๐Ÿ’ฅ

Tailwind Responsive Table


Before you get started here are a few things you should have:

  • A basic understanding of Tailwind
  • An actual <table> using semantic markup

The Problem

In the dynamic landscape of web design, the challenge of presenting tabular data in a responsive manner persists. Responsive tables adapt to varying screen sizes, ensuring usability across devices. However, they require careful consideration to maintain clarity and functionality.

Basic Tailwind Table

Let's start out with a basic <table> using some Tailwind classes.

<table class="min-w-full divide-y divide-slate-300">
  <thead class="bg-slate-50 dark:bg-slate-900">
      <th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold sm:pl-6">Name</th>
      <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold">Title</th>
      <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold">Email</th>
  <tbody class="bg-white divide-y divide-slate-200">
      <td class="py-4 pl-4 pr-3 text-sm font-medium whitespace-nowrap sm:pl-6">Lindsay Walton</td>
      <td class="px-3 py-4 text-sm text-slate-500 whitespace-nowrap">Front-end Developer</td>
      <td class="px-3 py-4 text-sm text-slate-500 whitespace-nowrap">[email protected]</td>
    <!-- More rows... -->

It should look something like this:

Name Title Email
Lindsay Walton Front-end Developer [email protected]

When resizing the viewport, you'll notice that a responsive table adjusts its width accordingly. This flexibility allows for smooth navigation on different devices. However, traditional tables face a limitation โ€“ their columns don't wrap automatically. This means that if you have lengthy content, such as email addresses or other non-breaking words, it could disrupt the table's layout.

To address this, you have two primary options:

  1. Column Wrapping: You can implement a solution to wrap the content within columns, ensuring readability without sacrificing the table's structure. This approach maintains the integrity of the data while accommodating various screen sizes.
  2. Side Scrolling: Alternatively, you can enable side scrolling for mobile devices, allowing users to scroll horizontally to view the entire table. While this preserves the table's layout, it may impact user experience, requiring additional effort to navigate.

In most cases, opting for column wrapping proves to be the preferred choice, as it enhances usability without complicating the interface. However, there are scenarios where hiding the table entirely on mobile devices may be more practical, especially if the table contains extensive or complex data that isn't easily digestible on smaller screens.

Ultimately, the decision depends on the specific requirements of your website and the nature of the data being presented. By understanding the nuances of responsive table design, you can ensure an optimal user experience across all devices.

We're going to assume you're here to wrap tables, so let's jump into that!

Wrapping table columns with Tailwind

Table Headings

Starting with <thead> we're going to change some of the default display properties based on break points.

<thead class="hidden sm:table-header-group">...</thead>

A few interesting things are happening here:

  • .hidden: This hides the whole <thead> for mobile devices.
  • .sm:table-header-group: This will turn <thead> back to it's original state for anything larger than a non-mobile device since .hidden is a bit destructive.

We really don't need to touch <tbody>, so next up is <tr>.

Table Rows

<tr class="flex flex-col sm:table-row">...</tr>

Breaking it down:

  • .flex: This turns our row into a flex container instead of a table-row, do we hear wrapping?
  • .flex-col: This turns our flex direction to column and now, we have wrapping!
  • .sm:table-row: Similarly, we were destructive with .flex earlier, so this will restore the tr to it's original state for non-mobile devices.

Table Columns

The real star of our show here is <td>:

<td data-label="Name" class="flex flex-col sm:table-cell before:content-[attr(data-label)] sm:before:content-none">...</td>

How it works:

  • data-label="name": This should match the table heading that is associated with this column. It needs to be on every <td>.
  • .flex: This turns our column into a flex container instead of a table-column.
  • .flex-col: This turns our flex direction to column.
  • .sm:table-cell: This will restore the tr to it's original state for non-mobile devices.
  • .before:content-[attr(data-label)]: This will grab the value in the data-label="name" attribute, and will render it with CSS.
  • .sm:before:content-none: This will hide the previous from rendering for non-mobile devices.

And there you have it! Your table should now be highly compatible with mobile devices. Perhaps not the most visually appealing.

Okay, it's really ugly and we hate that, so here's an opinionated example you can peep and customize fit up to your needs:

Sample table: A table design (built with Tailwind) that morphs into a beautiful vertical layout for small screens.
Alessandra Santelli At home training Soccer May 15, 2023 View
Giuliana Santelli At home training Soccer May 24, 2023 View

And one more with slightly different styling on CodePen: