Unit 8 of 15

Tables

Updated Jun 2026

Tables are for displaying data in rows and columns — think spreadsheets, schedules, and comparison charts. They’re often misused for page layout, but that role belongs to CSS. Use tables only for tabular data.

Concept 1 — The basic structure

A table is built from three nested tags: <table> wraps everything, <tr> defines each row, and <td> defines each data cell within a row.

<table>
  <tr>
    <td>HTML</td>
    <td>Structure</td>
    <td>1991</td>
  </tr>
  <tr>
    <td>CSS</td>
    <td>Style</td>
    <td>1996</td>
  </tr>
</table>

Every row must have the same number of cells, or the table will render unevenly.

Concept 2 — Header cells

Use <th> instead of <td> for column or row headers. The browser renders them bold and centred by default, and screen readers announce them as headers — making the table far easier to navigate.

<table>
  <tr>
    <th>Language</th>
    <th>Purpose</th>
    <th>Year</th>
  </tr>
  <tr>
    <td>HTML</td>
    <td>Structure</td>
    <td>1991</td>
  </tr>
  <tr>
    <td>CSS</td>
    <td>Style</td>
    <td>1996</td>
  </tr>
</table>

Concept 3 — thead, tbody, and tfoot

For anything beyond a tiny table, split the rows into semantic sections using <thead>, <tbody>, and <tfoot>. This helps browsers, screen readers, and CSS target each section independently.

<table>
  <thead>
    <tr>
      <th>Item</th>
      <th>Quantity</th>
      <th>Price</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Notebook</td>
      <td>2</td>
      <td>$4.00</td>
    </tr>
    <tr>
      <td>Pen</td>
      <td>5</td>
      <td>$2.50</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>Total</td>
      <td>7</td>
      <td>$6.50</td>
    </tr>
  </tfoot>
</table>

Tip: <tfoot> always goes in the HTML before <tbody>, even though it renders at the bottom. This lets the browser display the footer before all the body rows have loaded on long tables.

Concept 4 — Spanning rows and columns

A cell can stretch across multiple columns with colspan, or multiple rows with rowspan. The value is the number of cells to span.

<table>
  <tr>
    <th colspan="2">Name</th>
    <th>Score</th>
  </tr>
  <tr>
    <td>First</td>
    <td>Last</td>
    <td>98</td>
  </tr>
</table>
<table>
  <tr>
    <td rowspan="2">Monday</td>
    <td>9am — Maths</td>
  </tr>
  <tr>
    <td>10am — English</td>
  </tr>
</table>

Rule: when using colspan or rowspan, reduce the number of <td> tags in the affected rows accordingly, or you’ll end up with extra unwanted columns.

Concept 5 — Accessible tables

For complex tables, add a <caption> as the first child of <table>. It acts as a title for the table and is announced by screen readers before the data.

<table>
  <caption>Web language comparison</caption>
  <thead>
    <tr>
      <th>Language</th>
      <th>Purpose</th>
      <th>Year</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>HTML</td>
      <td>Structure</td>
      <td>1991</td>
    </tr>
  </tbody>
</table>

Try it yourself

<body>
  <h1>My first table</h1>

  <table>
    <caption>Top 3 programming languages</caption>
    <thead>
      <tr>
        <th>Language</th>
        <th>Primary use</th>
        <th>Difficulty</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>HTML</td>
        <td>Web structure</td>
        <td>Beginner</td>
      </tr>
      <tr>
        <td>Python</td>
        <td>Data &amp; scripting</td>
        <td>Beginner</td>
      </tr>
      <tr>
        <td>Rust</td>
        <td>Systems programming</td>
        <td>Advanced</td>
      </tr>
    </tbody>
  </table>
</body>

Note the &amp; in the second row — this is an HTML entity for the & character. Special characters like <, >, and & need to be escaped in HTML content.

Quick reference

TagPurpose
<table>Table container
<tr>Table row
<td>Data cell
<th>Header cell (bold, centred)
<thead>Header section
<tbody>Body section
<tfoot>Footer section
<caption>Table title (accessibility)
colspan="N"Span N columns
rowspan="N"Span N rows