Responsive HTML Tables: How to Make Tables That Work on Mobile

Responsive HTML Tables: How to Make Tables That Work on Mobile

September 29, 2026

Why Responsive HTML Tables Break on Mobile

Tables are the best way to present structured data, such as pricing plans, product specs, schedules or comparison charts. But open a typical HTML table on a phone and you’ll often see the same problems: text squeezed into narrow columns, content cut off at the edge of the screen, or the whole page scrolling sideways.

The reason is simple. A table is a two-dimensional grid, and its width is the sum of all its columns. A table with six columns and some longer text easily needs 800 pixels or more, while most phones only have around 375 pixels to work with. Fixed widths (width: 900px), long words that can’t wrap and simply having too many columns all make it worse.

In this guide, you’ll learn four proven techniques for building a responsive table with HTML and CSS, how to do the same with Tailwind CSS, and how to skip the CSS work entirely with Table Generator.

The Semantic Base: Start With Proper HTML

Every responsive table technique starts with clean, semantic markup. Before you write a single line of CSS, make sure your table looks like this:

<table>
  <caption>Houseplant care guide</caption>
  <thead>
    <tr>
      <th scope="col">Plant</th>
      <th scope="col">Height</th>
      <th scope="col">Watering</th>
      <th scope="col">Temperature</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Snake Plant</th>
      <td>60 cm</td>
      <td>Every 14 days</td>
      <td>15-25 °C</td>
    </tr>
    <tr>
      <th scope="row">Peace Lily</th>
      <td>45 cm</td>
      <td>Every 10 days</td>
      <td>18-24 °C</td>
    </tr>
  </tbody>
</table>

Here’s what each element does:

Semantic tables are also good for SEO. Search engines can extract data from well-structured tables and sometimes show it directly in search results. A table made of <div> elements, or worse, an image of a table, gives them nothing to work with.

Technique 1: Horizontal Scroll Wrapper

The simplest and most robust way to make a table responsive is to let it scroll horizontally inside a container:

<div class="table-wrapper">
  <table>
    ...
  </table>
</div>
.table-wrapper {
  max-width: 100%;
  overflow-x: auto;
}

.table-wrapper table {
  min-width: 600px;
  border-collapse: collapse;
}

The wrapper never gets wider than its parent, and if the table needs more room, only the wrapper scrolls, not the whole page. The min-width on the table keeps the columns from being squeezed into unreadable slivers before scrolling kicks in.

To make the scroll area accessible for keyboard users, add tabindex="0", a role and a label so the container can be focused and scrolled with the arrow keys:

<div class="table-wrapper" tabindex="0" role="region" aria-label="Houseplant care guide">

Pros:

Cons:

For most tables, this is the right default. It’s also the approach Table Generator uses for its embeddable tables.

Technique 2: Stacked “Card” Layout

For tables where each row describes one item (a product, a person, an order), you can turn every row into a card on small screens. Each cell becomes its own line, with the column name shown next to the value.

First, add a data-label attribute with the column name to each cell:

<tr>
  <td data-label="Plant">Snake Plant</td>
  <td data-label="Height">60 cm</td>
  <td data-label="Watering">Every 14 days</td>
  <td data-label="Temperature">15-25 °C</td>
</tr>

Then use a media query to switch the table elements to block layout and show the labels with a ::before pseudo-element:

@media (max-width: 640px) {
  .card-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .card-table tr {
    display: block;
    margin-bottom: 1rem;
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
  }

  .card-table td {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid #f3f4f6;
  }

  .card-table td::before {
    content: attr(data-label);
    font-weight: 600;
  }
}

The header row is hidden visually but kept available for screen readers. Each row becomes a bordered card, and each cell shows its label on the left and its value on the right.

Pros:

Cons:

Technique 3: Sticky Header and First Column

When users scroll through a large table, they quickly lose track of which column or row they’re looking at. position: sticky keeps the header row and the first column in place:

.table-wrapper {
  max-width: 100%;
  max-height: 400px;
  overflow: auto;
}

.table-wrapper table {
  border-collapse: separate;
  border-spacing: 0;
}

.table-wrapper thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #f3f4f6;
}

.table-wrapper tbody th {
  position: sticky;
  left: 0;
  background: #ffffff;
}

.table-wrapper thead th:first-child {
  left: 0;
  z-index: 2;
}

A few details are important here:

This technique pairs perfectly with the horizontal scroll wrapper from technique 1 and is ideal for wide data tables, comparison tables and schedules.

Technique 4: Hiding Lower-Priority Columns

Not every column is equally important. On a small screen, you can hide columns that are nice to have but not essential:

<tr>
  <th scope="col">Plant</th>
  <th scope="col">Watering</th>
  <th scope="col" class="optional">Height</th>
  <th scope="col" class="optional">Temperature</th>
</tr>
@media (max-width: 640px) {
  .optional {
    display: none;
  }
}

Remember to add the class to both the header cell and the matching data cells in every row.

Pros:

Cons:

You can combine this with the scroll wrapper: hide the least important columns and let the rest scroll if they still don’t fit.

Responsive Tables With Tailwind CSS

If you’re using Tailwind CSS, you can build all of the patterns above with utility classes. Here’s a responsive table with a scroll wrapper, a sticky header, a sticky first column and a hidden column on small screens:

<div class="max-h-96 max-w-full overflow-auto rounded-lg border border-gray-200" tabindex="0" role="region" aria-label="Houseplant care guide">
  <table class="min-w-[600px] border-separate border-spacing-0 text-left text-sm">
    <caption class="sr-only">Houseplant care guide</caption>
    <thead>
      <tr>
        <th scope="col" class="sticky top-0 left-0 z-20 bg-gray-100 px-4 py-3 font-semibold text-gray-900">Plant</th>
        <th scope="col" class="sticky top-0 z-10 bg-gray-100 px-4 py-3 font-semibold text-gray-900">Watering</th>
        <th scope="col" class="sticky top-0 z-10 hidden bg-gray-100 px-4 py-3 font-semibold text-gray-900 sm:table-cell">Height</th>
        <th scope="col" class="sticky top-0 z-10 bg-gray-100 px-4 py-3 font-semibold text-gray-900">Temperature</th>
      </tr>
    </thead>
    <tbody class="text-gray-600">
      <tr class="even:bg-gray-50">
        <th scope="row" class="sticky left-0 border-t border-gray-200 bg-white px-4 py-3 font-medium text-gray-900">Snake Plant</th>
        <td class="border-t border-gray-200 px-4 py-3">Every 14 days</td>
        <td class="hidden border-t border-gray-200 px-4 py-3 sm:table-cell">60 cm</td>
        <td class="border-t border-gray-200 px-4 py-3">15-25 °C</td>
      </tr>
      <!-- more rows -->
    </tbody>
  </table>
</div>

The key utilities are:

For the card layout (technique 2), Tailwind’s responsive variants work too: use block sm:table-row on rows and block sm:table-cell on cells, and show the labels with before:content-[attr(data-label)] sm:before:content-none.

By the way: Table Generator can export any table as HTML with Tailwind CSS classes already applied, so you don’t have to write them by hand.

Styling Basics for Readable Tables

A responsive table also needs to be easy to read. A few simple rules go a long way:

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  line-height: 1.5;
}

th,
td {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid #e5e7eb;
  text-align: left;
  vertical-align: top;
}

thead th {
  background: #f3f4f6;
  font-weight: 600;
}

tbody tr:nth-child(even) {
  background: #f9fafb;
}

td.number {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

Common Mistakes to Avoid

Using tables for layout. Tables are for tabular data, not for positioning content on a page. Use CSS Grid or Flexbox for layouts. Layout tables confuse screen readers and are nearly impossible to make responsive.

Missing header cells. Using <td> with bold text instead of <th> might look the same, but screen readers and search engines can’t tell which cells are headers. Always use <th> with a scope attribute.

Publishing tables as images. A screenshot of a table can’t be read by screen readers (unless it has a detailed alt text), can’t be indexed by search engines, can’t be copied and doesn’t scale on small screens. If you need an image for social media or a presentation, use it in addition to a real HTML table on your website, not instead of it.

Setting fixed widths. A width="900" attribute or a fixed width in pixels guarantees overflow on mobile. Use max-width: 100% on the container and let the content define the column widths.

Forgetting to test on real devices. Browser developer tools are great, but always check your table on an actual phone. Touch scrolling, font rendering and screen sizes can behave differently.

Skip the CSS: Generate a Responsive Table

If you don’t want to write and maintain all this CSS yourself, Table Generator does it for you. Create your table in the visual editor, style it with borders, stripes, colors and font sizes, and export it in the format you need:

Here’s a live example created with Table Generator and embedded into this page. Try resizing your browser window or opening this page on your phone to see how it adapts:

Technique Best For Keeps Table Structure Horizontal Scrolling Effort
Horizontal scroll wrapper Any table, especially wide data tables Yes Yes Low
Stacked card layout Lists of items, like products or contacts No No Medium
Sticky header and first column Large tables and comparison charts Yes Yes Medium
Hiding columns Tables with optional, secondary data Yes Reduced Low
Table Generator embed Websites and site builders without custom CSS Yes Only when needed None

New to Table Generator? Read our introduction to Table Generator for an overview of all features and export options.

Frequently Asked Questions

How do I make an HTML table responsive?

The easiest way is to wrap the table in a <div> with overflow-x: auto and max-width: 100%. The table can then scroll horizontally on small screens without breaking the page layout. For more advanced layouts, you can turn rows into cards, make the header sticky or hide less important columns with media queries.

Can I make a responsive table without CSS?

Not with plain HTML alone. HTML defines the structure of a table, and CSS controls how it behaves on different screen sizes. If you don’t want to write CSS, you can use a tool like Table Generator to create a table that’s responsive out of the box and embed it on your website.

What is the best way to display a table on mobile?

It depends on the data. For data that users need to compare across rows and columns, a horizontal scroll wrapper with a sticky first column works best. For lists of items that users read one at a time, a stacked card layout is often easier to read on a phone.

Should I use a table or CSS Grid?

Use a <table> for tabular data, where values are related across both rows and columns. Use CSS Grid for page layouts and card grids. Tables give screen readers and search engines important information about the structure of your data that a grid of <div> elements can’t provide.

How do I make a responsive table with Tailwind CSS?

Wrap the table in a <div> with overflow-auto max-w-full, use sticky top-0 for a sticky header and hidden sm:table-cell to hide columns on small screens. Or create your table in Table Generator and export it as HTML with Tailwind CSS classes.

Create Your Responsive Table Now

Building responsive tables by hand takes time, and every new table means repeating the same work. With Table Generator, you can create a beautiful, responsive table in minutes and export it as embeddable HTML, Tailwind CSS, plain HTML, PNG, PDF and more. Give it a try, it’s free!

Related Articles

Markdown Table Syntax: The Complete Guide (with Examples and a Generator)September 22, 2026

Markdown Table Syntax: The Complete Guide (with Examples and a Generator)

Learn Markdown table syntax with copyable examples: pipes, alignment, formatting inside cells, GitHub vs. GitLab vs. Notion, limitations, and a free Markdown table generator.

Read more about Markdown Table Syntax: The Complete Guide (with Examples and a Generator)
How to Add a Table in WordPress (3 Easy Ways, No Plugin Needed)September 15, 2026

How to Add a Table in WordPress (3 Easy Ways, No Plugin Needed)

Learn how to add a table in WordPress without a plugin: use the built-in Table block, weigh up table plugins, or embed a styled table that keeps its look in any theme.

Read more about How to Add a Table in WordPress (3 Easy Ways, No Plugin Needed)
Why Web Components for Table Embedding Simply Make SenseDecember 20, 2023

Why Web Components for Table Embedding Simply Make Sense

Discover the power of Web Components with Table Generator for beautiful, consistent tables on any platform. Easily embed tables with responsive design and enhanced search engine visibility.

Read more about Why Web Components for Table Embedding Simply Make Sense