HTML Tables

Show data in rows and columns with headers, captions and merged cells.

Lesson 18 of 44Beginner13 min read

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

ElementMeaning
<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.

HTML
<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" or scope="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:

CSS
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> with scope so screen readers can follow the data.
  • <thead>, <tbody> and <tfoot> group the parts of a large table.
  • colspan and rowspan merge 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.

Example 1

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>
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 2The caption names the table.
  2. Lines 3 to 7The first row uses <th> for column headers.
  3. Lines 8 to 12Each data row has one <td> per column.
  4. Lines 20 to 23A little CSS so the grid lines show.
Example 2

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>
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 3 to 5<thead> holds the header row. scope="col" marks column headers.
  2. Line 7Row headers use <th scope="row">, so the item name labels the whole row.
  3. Lines 10 to 12<tfoot> holds the total. colspan="2" makes "Total" stretch over two columns.
Example 3

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>
ResultEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Line 3rowspan="2" makes Maths fill Monday at 9:00 and 10:00.
  2. Line 4So the 10:00 row has only two cells, because Monday is already taken.

Common HTML Table Mistakes

Using tables for page layout

Don't
<table>
  <tr><td>Sidebar</td><td>Main content</td></tr>
</table>
Do
<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

Don't
<tr><th>Name</th><th>Age</th></tr>
<tr><td>Ana</td><td>12</td><td>London</td></tr>
Do
<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.

Fill in the blankseasy

Complete the table row with two data cells.

<table>
  <tr><th>Pet</th><th>Name</th></tr>
  <><>Cat</td><td>Mochi</td></tr>
</table>
Multiple choiceeasy

Which element creates a header cell?

Multiple choicemedium

A cell should stretch across 3 columns. What do you write?

Fix the bughard

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>
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • The header row uses two <th>
  • Every row has exactly 2 cells
  • The Pro price mentions £9

HTML Table Quiz

4 questions to check what you learned.

  1. What does <tr> stand for?

    • table record
    • table row
    • text row
    • top row
  2. Which element gives a table a title that screen readers announce?

    • <caption>
    • <title>
    • <th>
    • <legend>
  3. 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
  4. 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:

  1. A <caption>: Planet facts
  2. A <thead> row with three <th>: Planet, Moons, Day length
  3. A <tbody> with at least 3 planets
<table>

</table>
ResultEdit the code, then press Run or Ctrl+Enter
Checks
  • The caption says "Planet facts"
  • thead has 3 th cells
  • tbody has 3+ rows
  • Every body row has 3 cells