Tables
Last updated:
Practical patterns for semantic table markup, responsive behaviour, and data users can actually compare.
01 — Foundation
Tables are for tabular data
Good tables help users compare information. Bad tables create confusion and horizontal-scroll despair.
Tables belong to data with meaningful row and column relationships — not layout hacks, div grids pretending to be spreadsheets, or dashboards that dump the database onto the screen.
This pattern defines practical expectations for accessible, maintainable, responsive tables — real usability, not spreadsheet cosplay.
02 — When
Use tables for real relationships
If content needs comparison across rows and columns, a table is probably correct.
- pricing comparisons, schedules, invoices, and reports
- product specifications, analytics, and financial summaries
- not page layout, spacing, or component positioning — use Grid or Flexbox
03 — Semantics
Semantic structure
The browser and assistive technology already understand table markup — use it correctly.
Required structure
table,thead,tbody,tr,th, andtd— not div-based fake tablesth scope="col"for column headings andscope="row"for row headings where appropriatecaptionwhen the table needs context — especially for complex data
<table>
<caption>Quarterly sales performance</caption>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Q1</th>
<th scope="col">Q2</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Widget Pro</th>
<td>£12,400</td>
<td>£14,200</td>
</tr>
</tbody>
</table>04 — Clarity
Keep tables understandable
Complexity kills usability quickly.
- avoid endless columns, nested tables, and merged-cell chaos
- if comprehension needs emotional preparation, simplify the presentation
- consider summaries, grouping, charts, or exports instead of one giant dump
05 — Responsive
Responsive behaviour
Preserve semantics and relationships — horizontal scroll is often the right answer.
- keep tables readable, scrollable, and accessible on small screens
- make horizontal overflow obvious — do not clip content silently
- use sticky headers carefully on long tables — avoid overlap chaos on mobile
- do not destroy row/column meaning with “card mode” when comparison still matters
06 — Interaction
Sorting, filtering, and states
Interactive tables must expose state clearly and stay predictable.
- show sort direction and keep sorting keyboard accessible without layout jumps
- show active filters, result counts, and how to reset
- meaningful empty states — not generic “No data”
- calm loading for large datasets — avoid skeleton theatre for small ones
Too vague
'No data'Clearer
'No invoices found for this date range'07 — Accessibility
Accessibility and keyboard use
Structure matters enormously for screen readers, keyboard users, and zoom.
- logical reading order, visible focus, contrast, and readable spacing
- keyboard access for sorting, filtering, expandable rows, and inline actions
- touch targets large enough — not tiny icon-only controls packed together
08 — Performance
Export, performance, and enhancement
Large tables need care — but do not destroy accessibility for rendering benchmarks.
- offer CSV or other exports when users need data outside the interface
- watch DOM size and rendering cost on huge datasets — virtualise responsibly
- data and relationships should make sense before JavaScript enhancement runs
Anti-patterns to avoid
- tables used for layout
- div-based fake tables with broken semantics
- endless horizontal data users need binoculars to parse
- responsive card layouts that destroy comparison when the table should stay a table
09 — Review
Before you approve
A short checklist for tables in code review.
- genuinely tabular data with correct semantics
- headings, captions, and logical structure
- responsive behaviour that preserves meaning
- sorting, filtering, and empty states are understandable
- keyboard and touch use work end to end
- performance remains acceptable at realistic data sizes
When in doubt, ask: Does this help users understand relationships clearly, or merely dump information onto the screen? If the answer is “dump information”, the table is not finished.