Rows & Cells (<tr>, <td>, <th>)
Every HTML table is built from three elements repeated over and over: <tr> for rows, and
<td>/<th> for the cells inside each row. Getting these three right — especially the{' '}
scope attribute on <th> — is what separates a merely-visual table from an accessible one.
<tr> — Table Row
<tr> (table row) is a direct wrapper around a set of cells. A table is simply a stack of{' '}
<tr> elements, each containing the same number of cells (accounting for any colspan).
<table>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
<tr>
<td>Ada Lovelace</td>
<td>Mathematician</td>
</tr>
</table><td> — Table Data Cell
<td> holds a plain data value — the actual content of the table, as opposed to a label
describing it. Browsers render <td> with normal-weight, left-aligned text by default.
<tr> <td>Ada Lovelace</td> <td>Mathematician</td> <td>1815</td> </tr>
<th> — Table Header Cell
<th> marks a cell as a header — a label that describes an entire row or column of data.
Browsers render it bold and centered by default, but the important part is semantic, not
visual: assistive technology associates every <td> in that row/column with its <th>.
<tr> <th>Name</th> <th>Role</th> <th>Born</th> </tr>
<th> just because you want bold, centered text — that's a CSS job (font-weight, text-align). Use <th> only for cells that genuinely act as a header for other cells.The scope Attribute
scope tells assistive technology exactly what a <th> is a header FOR — an entire column, an
entire row, or a group of columns/rows. Without it, a screen reader has to guess based on
position, which works for simple tables but fails on complex ones.
scope value | Meaning |
|---|---|
col | This header describes every cell in its column |
row | This header describes every cell in its row |
colgroup | This header describes a group of columns (used with colspan) |
rowgroup | This header describes a group of rows (used with rowspan) |
<table>
<tr>
<th scope="col">Name</th>
<th scope="col">Role</th>
<th scope="col">Born</th>
</tr>
<tr>
<th scope="row">Ada Lovelace</th>
<td>Mathematician</td>
<td>1815</td>
</tr>
<tr>
<th scope="row">Grace Hopper</th>
<td>Computer scientist</td>
<td>1906</td>
</tr>
</table>scope="col") labels each column, and the leftmost cell in each data row (scope="row") labels that row. A screen reader announcing the "1906" cell can now say "Born, Grace Hopper, 1906" — both headers, automatically.Header Cell Association in Practice
When a screen reader user moves focus to a data cell in table navigation mode, it reads the cell's value together with the header(s) that describe it — the column header, and (if scope is set) the row header too.
Screen reader announces when landing on the "1906" cell: "Born, column 3. Grace Hopper, row 3. 1906."
scope="col" to header rows and scope="row" to header columns, even in simple tables. It costs nothing visually and makes every table properly navigable with a screen reader.Cells Don't Have to Be Text
<td> and <th> can contain any flow content — links, images, lists, even nested tables (used
sparingly). The cell is just a container.
<tr> <th scope="row">Profile</th> <td><img src="avatar.jpg" alt="Ada Lovelace portrait" width="40" height="40"></td> <td><a href="/people/ada-lovelace">View profile</a></td> </tr>
Common Mistakes
Mismatched cell counts — every
<tr>in a table (accounting for colspan) should add up to the same number of columns.Using <th> purely for visual styling instead of semantic headers.Skipping
scopeon header cells in tables with headers in both directions.Nesting a block element like
<div>directly inside<table>/<tr>outside of a<td>/<th>— the browser will silently move or drop it.
Key Takeaways
<tr> is a row; <td> is a plain data cell; <th> is a header cell.
<th> is semantic, not just a bold/centered style — use CSS for pure visual formatting.
scope="col" and scope="row" explicitly associate a header with the cells it describes.
Tables with headers in both directions (row AND column headers) need scope on both to be fully accessible.
Cells can contain any flow content, not just plain text.