Tables show up wherever data lines up in rows and columns: price lists, timetables, scoreboards. They have a few moving parts, but the structure is logical once you see it. We'll also clear up the most important myth about tables.
1The parts of a table
A table is built from a handful of nested elements:
| Element | Role |
|---|---|
<table> | The whole table. |
<tr> | A table row. |
<th> | A header cell (bold, and announced as a header by screen readers). |
<td> | A normal data cell. |
<caption> | A title for the table — the first child of <table>. |
Group rows with <thead> (header rows) and <tbody> (the data) for clarity and styling.
<table>
<caption>Class timetable</caption>
<thead>
<tr><th>Day</th><th>Subject</th></tr>
</thead>
<tbody>
<tr><td>Mon</td><td>Maths</td></tr>
</tbody>
</table>
<table>holds rows (<tr>); rows hold header cells (<th>) and data cells (<td>).<caption>titles the table and should be its first child.- Group rows with
<thead>and<tbody>.
2Accessible tables — and the layout myth
Use <th> for header cells, not styled <td>. Screen readers use them to announce "Day: Monday, Subject: Maths" instead of reading a wall of disconnected values. For complex tables, add scope="col" or scope="row" to say which way a header applies.
overflow-x: auto so it can scroll sideways instead of breaking the page.- Use
<th>for real header cells so screen readers can pair headers with data. - Add
scope="col"/scope="row"on headers in complex tables. - Never use tables for page layout — that's a job for CSS Flexbox/Grid.
★ Practical: a price list
In any playground, build a table with:
- A
<caption>titling the table. - A header row of
<th>cells inside<thead>. - At least three data rows inside
<tbody>. - Confirm you used
<th>for headers, not bold<td>.
Ready to test yourself?
Take the short quiz. Score 60% or more to mark this lesson complete.
Start the quiz →💡 Log in to save your progress and earn the certificate.