Tables display data in rows and columns: timetables, price comparisons, scoreboards and exam results. HTML builds a table one row at a time, and each row is made of cells.
One rule comes first: tables are for tabular data, not for page layout. Years ago, whole websites were laid out with tables, which made them hard to maintain and confusing for screen readers. Today layout is done with CSS Flexbox and CSS Grid, and tables are kept for information that really belongs in a grid.
A quick test: if the data would make sense in a spreadsheet, with a heading at the top of each column, it belongs in an HTML table.
The four core table elements
| Element | Meaning |
|---|---|
<table> | The whole table |
<tr> | Table row |
<th> | Table header cell: a column or row title (bold and centred by default) |
<td> | Table data cell: a normal value |
You build a table one <tr> at a time and put the cells inside each row. Every row should have the same number of cells, unless some cells are merged.
<table>
<tr><th>Day</th><th>Opens</th></tr>
<tr><td>Monday</td><td>9am</td></tr>
</table>Captions, headers and table sections
<caption>gives the table a visible title. Screen readers announce it first, so visitors know what the table is about before hearing the data.<thead>wraps the header rows,<tbody>holds the main data and<tfoot>holds totals or summaries. These sections make large tables easier to style and understand.scope="col"orscope="row"on a<th>tells assistive technology which cells that header describes.
Without proper <th> elements, a screen reader announces a table as a long stream of values with no labels, which is almost impossible to follow.
Merging cells with colspan and rowspan
colspan="2"makes a cell stretch across two columns.rowspan="2"makes a cell stretch down two rows.
When a cell spans, leave out the cells it covers in the other rows. If you forget, the table gains an extra column and everything shifts out of line.
Styling tables
A plain HTML table has no borders and very little spacing. A few lines of CSS make it readable:
table { border-collapse: collapse; }
th, td { border: 1px solid #ccc; padding: 8px 12px; }border-collapse: collapse merges the double borders between cells into single lines. You'll learn more about borders in CSS Borders.
HTML Table Syntax
Table skeleton
<table>
<caption>Title</caption>
<thead>
<tr><th>Header</th><th>Header</th></tr>
</thead>
<tbody>
<tr><td>Data</td><td>Data</td></tr>
</tbody>
</table>HTML Table Summary
- Use tables only for data that belongs in rows and columns, never for page layout.
<table>,<tr>,<th>and<td>are the four core elements.- Add a
<caption>and use<th>withscopeso screen readers can follow the data. <thead>,<tbody>and<tfoot>group the parts of a large table.colspanandrowspanmerge cells; remove the cells they cover.
HTML Table Examples
Each example runs in the page. Edit the code and press Run to see what changes.
A simple league table
The <style> just adds borders so you can see the cells. You'll learn CSS later.
<table>
<caption>Five-a-side league</caption>
<tr>
<th>Team</th>
<th>Played</th>
<th>Points</th>
</tr>
<tr>
<td>Red Rockets</td>
<td>6</td>
<td>15</td>
</tr>
<tr>
<td>Blue Bandits</td>
<td>6</td>
<td>12</td>
</tr>
</table>
<style>
table { border-collapse: collapse; }
th, td { border: 1px solid #999; padding: 6px 12px; }
</style>Line-by-line explanation
- Line 2The caption names the table.
- Lines 3 to 7The first row uses
<th>for column headers. - Lines 8 to 12Each data row has one
<td>per column. - Lines 20 to 23A little CSS so the grid lines show.
Sections, scope and a total row
<table>
<caption>Café order</caption>
<thead>
<tr><th scope="col">Item</th><th scope="col">Qty</th><th scope="col">Price</th></tr>
</thead>
<tbody>
<tr><th scope="row">Flat white</th><td>2</td><td>£6.40</td></tr>
<tr><th scope="row">Croissant</th><td>1</td><td>£2.80</td></tr>
</tbody>
<tfoot>
<tr><th scope="row" colspan="2">Total</th><td>£9.20</td></tr>
</tfoot>
</table>
<style>
table { border-collapse: collapse; font-family: sans-serif; }
th, td { border: 1px solid #ccc; padding: 6px 12px; text-align: left; }
thead, tfoot { background: #f3ede2; }
</style>Line-by-line explanation
- Lines 3 to 5
<thead>holds the header row.scope="col"marks column headers. - Line 7Row headers use
<th scope="row">, so the item name labels the whole row. - Lines 10 to 12
<tfoot>holds the total.colspan="2"makes "Total" stretch over two columns.
Rowspan in a timetable
<table>
<tr><th>Time</th><th>Monday</th><th>Tuesday</th></tr>
<tr><td>9:00</td><td rowspan="2">Maths (double)</td><td>Art</td></tr>
<tr><td>10:00</td><td>Music</td></tr>
<tr><td>11:00</td><td>PE</td><td>Science</td></tr>
</table>
<style>
td, th { border: 1px solid #aaa; padding: 6px 10px; }
table { border-collapse: collapse; }
</style>Line-by-line explanation
- Line 3
rowspan="2"makes Maths fill Monday at 9:00 and 10:00. - Line 4So the 10:00 row has only two cells, because Monday is already taken.
Common HTML Table Mistakes
Using tables for page layout
<table>
<tr><td>Sidebar</td><td>Main content</td></tr>
</table><div class="layout">
<aside>Sidebar</aside>
<main>Main content</main>
</div>
<!-- layout handled by CSS Grid or Flexbox -->Layout tables confuse screen readers and are hard to make responsive.
Rows with the wrong number of cells
<tr><th>Name</th><th>Age</th></tr>
<tr><td>Ana</td><td>12</td><td>London</td></tr><tr><th>Name</th><th>Age</th><th>City</th></tr>
<tr><td>Ana</td><td>12</td><td>London</td></tr>Every row should add up to the same number of columns (counting colspan).
HTML Table in Real Projects
Tables in the wild
Bank statements, sports results, train times, pricing comparison grids and spreadsheet-style dashboards all use HTML tables. On phones, wide tables are usually wrapped in a container that scrolls sideways, just like the tables in this lesson.
HTML Table Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the table row with two data cells.
<table>
<tr><th>Pet</th><th>Name</th></tr>
<><>Cat</td><td>Mochi</td></tr>
</table>
<tr> and each value a <td>.tr, a normal cell is td.Which element creates a header cell?
<th> is a header cell; <thead> is the section that groups header rows.A cell should stretch across 3 columns. What do you write?
colspan spans columns; rowspan spans rows.This price table has a broken layout: the "Pro" row has an extra cell and the header row uses <td>. Fix it so every row has 2 cells and the header uses <th>.
<table>
<tr><td>Plan</td><td>Price</td></tr>
<tr><td>Free</td><td>£0</td></tr>
<tr><td>Pro</td><td>£9</td><td>per month</td></tr>
</table>- The header row uses two
<th> - Every row has exactly 2 cells
- The Pro price mentions £9
<th>, and each row must have the same number of columns.HTML Table Quiz
4 questions to check what you learned.
What does
<tr>stand for?- table record
- table row
- text row
- top row
Which element gives a table a title that screen readers announce?
<caption><title><th><legend>
Should you use tables to lay out a whole web page?
- Yes, it's the standard way
- Only on mobile
- No, use CSS Flexbox or Grid; tables are for data
- Only for footers
In a row where one cell has
rowspan="2", what happens to the next row?- It needs an extra cell
- Nothing changes
- It needs one fewer cell, because that space is taken
- It's deleted
HTML Table Challenge
Build a planet facts table
Create a table with:
- A
<caption>: Planet facts - A
<thead>row with three<th>: Planet, Moons, Day length - A
<tbody>with at least 3 planets
<table>
</table>- The caption says "Planet facts"
- thead has 3 th cells
- tbody has 3+ rows
- Every body row has 3 cells
<caption>, then <thead>, then <tbody>.