`<table>` Is for Tabular Data — Not Layout
Tables
Tables represent data in rows and columns. They're not for page layout — that's flexbox and grid.
What you'll learn
- Build a real data table
- Use `<thead>` / `<tbody>` / `<th>` / `scope`
- Recognize when NOT to use a table
A table represents data in rows and columns. The semantic elements
(<table>, <thead>, <tbody>, <th>, <td>) communicate
structure to screen readers and search engines.
A Real Data Table
<table>
<caption>Server response times (ms)</caption>
<thead>
<tr>
<th scope="col">Endpoint</th>
<th scope="col">p50</th>
<th scope="col">p99</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">/api/users</th>
<td>12</td>
<td>104</td>
</tr>
<tr>
<th scope="row">/api/posts</th>
<td>23</td>
<td>180</td>
</tr>
</tbody>
</table> The Tags
| Tag | What it is |
|---|---|
<table> | The whole table |
<caption> | A title for the table — for screen readers |
<thead> | Header rows group |
<tbody> | Data rows group |
<tfoot> | Footer rows (totals, etc.) |
<tr> | A row |
<th> | A header cell |
<td> | A data cell |
scope on <th>
<th scope="col">Endpoint</th> <!-- header for a column -->
<th scope="row">/api/users</th> <!-- header for a row --> Helps screen readers announce the right header when reading a cell.
Spanning
<td colspan="2">Spans two columns</td>
<td rowspan="3">Spans three rows</td> Tables Are Not For Layout
Before flexbox and grid, tables were sometimes used to position columns. Don’t do this — for visual layout, use CSS. Tables are for actual tabular data.
Styling Tip — A Sensible Default
A bit of CSS goes a long way:
table {
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 0.5rem 0.75rem;
text-align: left;
}
th {
border-bottom: 2px solid currentColor;
}
tbody tr:nth-child(odd) {
background: rgb(0 0 0 / 5%);
} Up Next
Forms — how the web gets input from users.
Forms Intro →