Lesson · Beginner
Tables for data
Mark up genuine row-and-column data with captions and headers while keeping layout responsibilities in CSS.
- Published
- Last checked
Tables express data relationships
Use a table when a reader needs to compare values across rows and columns. Do not use a table to arrange the overall page.
<table>
<caption>
Workshop times
</caption>
<thead>
<tr>
<th scope="col">Topic</th>
<th scope="col">Time</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">HTML basics</th>
<td>9:00 a.m.</td>
</tr>
</tbody>
</table>
The caption names the dataset. Header cells and their scope make the relationships explicit when the visual grid is not available.
Responsive behavior
First remove unnecessary columns or rephrase dense content. When horizontal space still cannot fit genuine tabular data, place the table in a labeled scroll container rather than clipping it.
How browsers actually behave
The browser builds a table model from row groups, rows, headers, and data cells.
Simple header relationships can be inferred from position and scope; complex
tables may need explicit identifiers. Visual borders do not create those
relationships, and changing table elements to display: block can alter how
some accessibility APIs expose them.
Column widths are negotiated from available space, cell content, and CSS. Long unbreakable values can widen the entire table. That overflow belongs to the table region, not the whole page, when the data genuinely cannot reflow.
Decisions and trade-offs
Use a table only when a reader benefits from comparing values across rows or columns. Use a list for a sequence and CSS grid for page layout. Keep tables simple when possible: one caption, clear headers, and one fact per cell. Split a very complex matrix if separate tables better answer separate questions.
Responsive card transformations duplicate header labels and can obscure relationships. A bounded horizontal scroll is often more honest for compact data, provided the scroll region is labeled, keyboard reachable when necessary, and visually indicated.
Accessibility consequences
A useful caption names the table's purpose; nearby prose can explain how to interpret it. Header text should be concise and unique. Do not rely on color or alignment alone to distinguish totals, status, or unavailable values.
Screen magnification makes cross-axis tracking difficult. Freeze headers only when they do not obscure content at high zoom, and preserve a logical focus order for interactive cells.
Common failures and fixes
- A screen reader announces values without context. Header cells use
tdor lack scope. Mark real headers and test cell navigation. - The page scrolls sideways. The table is not locally bounded. Add a labeled overflow wrapper and keep page overflow visible.
- The table is really a two-column layout. Cells contain unrelated labels and prose. Replace it with headings, a list, or a description list.
- Sorting changes values but not state. A custom sorter omits the current direction. Update visible text and the header's sort state together.
Verify it
Read each data cell with its row and column header, then inspect the accessibility tree. Disable CSS to confirm the relationships remain. Test the table at 320 CSS pixels and 200% zoom, including keyboard access to a local overflow region. Sort or filter if supported, confirm focus remains stable, and validate the markup for malformed rows or missing cells.
Exercise and next step
Create a comparison of three plans with two measurable features. Read each cell aloud with its row and column header. Next, apply the same explicit-label discipline to form controls and errors.
Boundary of this lesson
Table semantics cannot rescue data that is incomparable, poorly defined, or overloaded with prose. Decide which question the grid answers and define units, time periods, missing values, and material exclusions in visible text. If a person must open several tooltips to understand every cell, the data model or page structure likely needs simplification. Export and print views may also need separate verification even when the on-screen table is sound.
Practice with responsive data
Build one small comparison with a long product name, a missing value, a total, and an interactive sort. At narrow width, compare local horizontal scrolling with a card transformation. Keep the version that preserves header relationships and makes comparison easiest, then test it with a screen reader and magnification. Document units and missing-value meaning so visual and programmatic structure carry the same facts.
Export or print the same data once. Header text, units, totals, and missing-value meaning must survive without hover help, sticky positioning, or interactive sorting. If the static result becomes ambiguous, add visible context to the table rather than relying on behavior that exists only in the screen version.
Free template + launch checklist
Build a page you can check before launch
Start with one reviewed semantic HTML page, then work through the one-page checklist against your published URL.