Example 1 — Basic Table
<table>
<tr><td>Apple</td><td>Red</td></tr>
<tr><td>Banana</td><td>Yellow</td></tr>
</table> How It Works
- table wraps the grid.
- tr creates each row.
- td holds one data cell.
- Next step — add
thheaders for real datasets.

An HTML table presents tabular data—information arranged in rows and columns so you can look up a value by matching a row with a column (price lists, schedules, scores, employee directories).
Start with <table>, put each row in <tr>, and put each cell in <td> (data) or <th> (header). Optional caption, thead, tbody, and tfoot make larger tables clearer.
Do not use tables to lay out a whole webpage (sidebars, headers, multi-column design). That belongs to CSS. Tables used only for layout are hard for assistive tech and brittle to maintain.
Sighted users connect cells visually to headers. Screen readers do the same when you mark headers with th (and scope when helpful). Good structure makes both paths work.
Ask: “Is this a grid of related values?” If yes, a table fits. If you only need a list, use lists.
Build page layout with CSS Flexbox or Grid. Keep <table> for real data.
This tutorial teaches table structure on HTML pages. Attribute-level detail for the element itself is on HTML table Tag.
Minimal table, then a structured table with headers and sections:
<table>
<tr>
<td>Apple</td>
<td>Red</td>
</tr>
<tr>
<td>Banana</td>
<td>Yellow</td>
</tr>
</table> <table>
<caption>Store prices</caption>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Notebook</td>
<td>$4.99</td>
</tr>
</tbody>
</table> Building blocks of an HTML data table:
| Element | Role |
|---|---|
<table> | Container for the whole grid |
<caption> | Visible title describing the table |
<tr> | One table row |
<th> | Header cell (column or row label) |
<td> | Data cell |
<thead> / <tbody> / <tfoot> | Header, body, and footer row groups |
colspan / rowspan | Merge a cell across columns or rows |
scope | Hints whether a th labels a col or row |
| Content | Use a table? |
|---|---|
| Price list, timetable, spreadsheet-like data | Yes |
| Simple bullet features | No — use a list |
| Two-column page layout | No — use CSS layout |
| Form fields in a grid of labels + inputs | Prefer form layout / CSS; tables only if it is truly tabular |
| Attribute | Meaning |
|---|---|
colspan="2" | Cell covers two columns |
rowspan="2" | Cell covers two rows |
A practical workflow:
<table>; add an optional <caption>.<th> (often inside <thead>).<tr> + <td> (often inside <tbody>).tfoot for totals; use colspan/rowspan only when needed.border-collapse, padding)—not presentational HTML attributes from the 1990s.| Goal | HTML pattern |
|---|---|
| Simple grid | table > tr > td |
| Labeled columns | thead > tr > th + tbody |
| Title above the table | <caption>…</caption> first child |
| Merged header | <th colspan="2"> |
| Readable borders | CSS border-collapse: collapse |
Toggle header cells and a caption on a small product table.
Six patterns: basic grid, headers, sections, spanning, CSS styling, and a full employee table.
<table>
<tr><td>Apple</td><td>Red</td></tr>
<tr><td>Banana</td><td>Yellow</td></tr>
</table> th headers for real datasets.<table>
<thead>
<tr><th>Product</th><th>Price</th></tr>
</thead>
<tbody>
<tr><td>Notebook</td><td>$4.99</td></tr>
<tr><td>Pen</td><td>$1.25</td></tr>
</tbody>
</table> <table>
<thead>
<tr><th>Item</th><th>Qty</th><th>Cost</th></tr>
</thead>
<tbody>
<tr><td>Coffee</td><td>2</td><td>$6.00</td></tr>
<tr><td>Bagel</td><td>1</td><td>$3.50</td></tr>
</tbody>
<tfoot>
<tr><td colspan="2">Total</td><td>$9.50</td></tr>
</tfoot>
</table> <table>
<tr><th colspan="2">Schedule</th></tr>
<tr>
<td rowspan="2">Mon</td>
<td>Math</td>
</tr>
<tr><td>Science</td></tr>
</table> <style>
table { width: 100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 8px; }
th { background: #f4f4f4; }
tr:nth-child(even) { background: #f9f9f9; }
</style>
<table>
<thead><tr><th>Name</th><th>Score</th></tr></thead>
<tbody>
<tr><td>Alice</td><td>92</td></tr>
<tr><td>Bob</td><td>85</td></tr>
</tbody>
</table> :nth-child, not extra HTML.<table>
<caption>Employee List</caption>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Position</th>
<th>Department</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>John Doe</td>
<td>Software Engineer</td>
<td>Development</td>
</tr>
<tr>
<td>2</td>
<td>Jane Smith</td>
<td>Project Manager</td>
<td>Operations</td>
</tr>
</tbody>
</table> Most table problems are layout misuse, missing headers, or broken spans.
Use CSS for columns and sidebars. Reserve tables for data.
Fake headers look bold but are not announced as headers. Use th.
Count cells carefully so each row still adds up to the same column total.
Wrap the table in a scroll container or redesign for narrow viewports.
Prefer CSS over old border, bgcolor, and align attributes.
Add a caption (or nearby heading) so users know what the data describes.
HTML tables (table, tr, th, td, thead/tbody/tfoot, caption) are Baseline and work in every browser. Style with CSS; keep markup semantic.
Tabular markup is supported everywhere the web is rendered.
Bottom line: Use tables for data with real headers—never for whole-page layout.
One line: Put related values in rows and columns with table, label them with th, and leave layout to CSS.
Open a Try It demo and build a full data table with headers and CSS.
8 people found this page helpful