DEV Community

Nick Benksim
Nick Benksim

Posted on • Originally published at csscodelab.com

Adaptive Data Tables in Pure CSS

The Eternal Struggle: Tables vs. Small Screens

Grab a coffee, because we need to talk about the one thing that still makes senior devs sweat: responsive tables. We've all been there. You build a gorgeous data dashboard, everything looks crisp on your 27-inch iMac, and then the product manager opens it on an iPhone 13. Suddenly, your layout is blown out, horizontal scrollbars appear like uninvited guests, and the data becomes a scrambled mess. Tables are inherently rigid; they want to expand horizontally, but mobile screens are narrow. It’s a classic conflict of interest.

How We Suffered Before (The Dark Ages)

In the old days, we had two main "solutions," and both kind of sucked. First, there was the overflow-x: auto trick. We just wrapped the table in a div and let the user swipe horizontally. It’s functional, sure, but it’s a terrible user experience because you lose the context of the first column as you scroll. It feels like looking at data through a keyhole.

Then came the "double data" hack. We used to hide the table on mobile and show a completely different set of stacked divs or cards. Maintaining two versions of the same data was a nightmare for synchronization and performance. Some of us even tried the data-label attribute trick where we used CSS content: attr(data-label) to inject headers into every cell. It worked, but it felt like we were fighting the browser rather than working with it.

The Modern Way in 2026: Container Queries and Grid Magic

Today, we don't have to choose between "broken" and "duplicate." With the maturity of CSS Container Queries and the flexibility of Grid, we can make tables truly fluid. Instead of relying on the global viewport size, we can tell our table to transform based on the space available to its own container. This is particularly useful for modular dashboards.

To make the text scale perfectly within these shrinking cells, I highly recommend using responsive (fluid) typography with the clamp() function. It prevents your table headers from becoming massive on tablets while staying readable on small phones. Additionally, using logical properties of CSS ensures your padding and margins behave correctly if your data ever needs to support Right-to-Left languages without rewriting the whole stylesheet.

The strategy is simple: on large screens, it’s a standard table. As soon as the container gets too narrow, we flip the display property to block or grid, and use pseudo-elements to reconstruct the headers for a "card-like" mobile view.

Ready-to-Use Code Snippet

Here is a robust, pure CSS solution that transforms a standard HTML table into a vertical stack when space is tight. No JavaScript required.


/* Container setup for modern responsiveness */
.table-container {
  container-type: inline-size;
  width: 100%;
}

.responsive-table {
  width: 100%;
  border-collapse: collapse;
  margin: 1rem 0;
}

.responsive-table th, 
.responsive-table td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #eee;
}

/* The Magic Transformation */
@container (max-width: 600px) {
  .responsive-table thead {
    display: none; /* Hide original headers */
  }

  .responsive-table tr {
    display: block;
    margin-bottom: 1rem;
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 10px;
  }

  .responsive-table td {
    display: flex;
    justify-content: space-between;
    font-size: 0.9rem;
    border-bottom: 1px dotted #ccc;
  }

  .responsive-table td:last-child {
    border-bottom: none;
  }

  /* Inject labels via data-attributes */
  .responsive-table td::before {
    content: attr(data-label);
    font-weight: bold;
    text-transform: uppercase;
    color: #666;
  }
}

Common Beginner Mistake: Forgetting Accessibility

The biggest mistake I see mid-level devs make is forgetting that display: block or display: grid on table elements can actually strip away the table's semantic meaning for screen readers. In some browsers, if a <table> is no longer display: table, it's just a bunch of boxes to an assistive device.

To fix this, if you are radically changing the display properties, you should add ARIA roles (role="table", role="row", role="cell") to your HTML tags. This ensures that while the table looks like a list of cards to a mobile user, it still acts like a structured data table for someone using a screen reader. Don't sacrifice inclusivity for a fancy layout!

🔥 We publish more advanced CSS tricks, ready-to-use snippets, and tutorials in our Telegram channel. Subscribe so you don't miss out!

Top comments (0)