// blog/developer/
Back to Blog
Developer · July 27, 2026 · 8 min read · Updated May 22, 2026

HTML Table Generator: Responsive Tables That Survive Mobile

HTML Table Generator: Responsive Tables That Survive Mobile

HTML tables have a reputation problem. Two decades ago developers used them for page layout, which broke accessibility and turned maintenance into a nightmare. The backlash pushed many engineers to avoid

even for the one job it does well: rows and columns of related data.

A real table is the right element when the cell at row 4, column 2 means something. Product comparisons, pricing plans, schedules, KPI dashboards, sport standings. A

grid does not give screen readers any of that semantic information.

The hard part is mobile. A six-column report that fits a 1440px monitor becomes a horizontal scroll on a 375px phone. That is a CSS problem, sometimes a layout problem, and occasionally a sign you should not be using a table at all.

* * *

Semantic Table Markup

A correct table uses every group element:

`html

Monthly Sales Report
Product Q1 Q2 Q3
Widget A 1,200 1,450 1,600
Widget B 800 920 1,100
Total 2,000 2,370 2,700
`

: one-line description. Screen readers announce it before reading any rows.

, , : row groups. Browsers can scroll the body while keeping the header in place; screen readers use the grouping to navigate.

with scope: marks header cells with scope="col" or scope="row". Skip this and screen reader users have no way to know which header belongs to which cell.

If your data lives in a spreadsheet, dump it to CSV and convert with the JSON to CSV tool (it converts both directions). When the HTML is ready for production, run it through the HTML Minifier to drop whitespace.

Data table displayed on desktop and mobile screens
Data table displayed on desktop and mobile screens
* * *

Three Patterns That Survive Mobile

Pick the pattern that matches the data.

1. Horizontal scroll (simplest, no markup change):

`css .table-container { overflow-x: auto; -webkit-overflow-scrolling: touch; } `

Wraps the table in a scrollable container. The structure stays intact. Good when every column carries equal weight.

2. Stacked rows (most readable on phones):

`css @media (max-width: 768px) { table, thead, tbody, th, td, tr { display: block; } thead { display: none; } td { position: relative; padding-left: 50%; } td::before { content: attr(data-label); position: absolute; left: 0; width: 45%; font-weight: bold; } } `

Each row turns into a card with labeled values. Requires data-label attributes on every . Best for 4 to 8 column tables where every value matters.

3. Column hiding (selective):

`css @media (max-width: 768px) { .priority-low { display: none; } } `

Hide secondary columns on mobile and add a "show all" toggle. Best for tables with a clear primary view and optional detail columns.

For very wide tables, combine: hide low-priority columns, then scroll the remainder.

Key takeaway

Pick the pattern that matches the data.

* * *

CSS That Makes a Table Readable

Default tables look like a 1995 spreadsheet. A small ruleset fixes that:

`css table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }

th, td { padding: 12px 16px; text-align: left; border-bottom: 1px solid #e5e7eb; }

thead th { background-color: #f9fafb; font-weight: 600; color: #374151; text-transform: uppercase; font-size: 0.75rem; letter-spacing: 0.05em; }

tbody tr:hover { background-color: #f3f4f6; } tbody tr:nth-child(even) { background-color: #f9fafb; } `

The rules that earn their keep:

  • border-collapse: collapse removes the double border between cells. Set it on every table.
  • Zebra striping (:nth-child(even)) helps eyes track a row across many columns.
  • Hover highlighting tells the user which row is under the cursor.
  • Header styling (uppercase, smaller, tinted background) separates the header from the data.
  • Alignment matters: left-align text, right-align numbers so digit places line up, center checkmarks and status icons.

When the stylesheet ships, run it through the CSS Minifier to drop comments and whitespace.

* * *

Accessibility Checklist

Tables are one of the trickiest elements for screen reader users. Run through this every time:

  • Always include : a one-line description of the table. Hide it visually with CSS if you must, but never drop it from the markup.
  • with scope on every header: column headers get scope="col", row headers get scope="row". Without scope, the row/column relationship is lost.
  • Do not use tables for layout: if there is no row-column meaning, use CSS Grid or Flexbox. Layout tables make screen readers announce nonsense.
  • Avoid colspan and rowspan: merged cells confuse keyboard navigation. When merging is unavoidable, use id and headers to keep the relationship explicit.
  • Sortable headers: set aria-sort="ascending", "descending", or "none" on the active column header.
  • Stacked layout: keep data-label text identical to the column header text so screen readers do not announce two different names for the same value.
  • Color is never the only signal: pair red/green with a + or - sign, or with an icon, so color-blind users get the same information.
Developer building table layout in code editor
Developer building table layout in code editor
* * *

When Not to Use a Table

Some grids belong in a different element.

  • Cards: if every row is a self-contained item (product, person, project) with images and actions, a card grid reads better than a table, especially on mobile.
  • Definition lists: two-column "label / value" data fits a
    with
    and
    better than a table, and is easier to style responsively.
  • Charts: if the question is "what is the trend?", a line or bar chart answers it faster than rows of numbers.
  • Interactive data grids: filtering, grouping, pagination, virtualization, and cell editing all belong in a real grid component (AG Grid, TanStack Table). Trying to roll those on top of a styled
    ends in pain.

The test: does the cell at row X, column Y mean something specific? If yes, table. If you only have a list of items with properties, cards or a

will do better.

* * *

FAQ

Should I use a CSS framework for tables?

Tailwind and Bootstrap both ship table utilities that save time (Tailwind's divide-y and text-right are the two you will reach for most). For complex interactive tables, use a JS library like TanStack Table or AG Grid. For plain display tables, vanilla CSS is enough.

How do I make a table sortable?

For a static page, add click handlers on the elements that re-order the rows. For React or Vue, use TanStack Table for headless sort, filter, and pagination logic. For server-rendered pages, sort on the server and put the direction in a query parameter.

How many columns work on mobile?

Three or four columns fit a 375px screen without scrolling. Five to six need the stacked layout or horizontal scroll. Beyond six, switch to column hiding, expandable rows, or a card view.

Can I make table headers sticky?

Yes. position: sticky; top: 0; on the th elements keeps the header pinned while the body scrolls. Add a z-index and a solid background so cells do not bleed through.

Key takeaway

### Should I use a CSS framework for tables.