Skip to content
Laviyx Learn

Try

HTML course menu

Advanced HTML Tables: caption, thead, tbody, tfoot, colspan, rowspan and scope

Build accessible, well-structured HTML tables: add a caption, group rows with thead, tbody and tfoot, merge cells with colspan and rowspan, set the scope of header cells, and style columns with colgroup.

Beginner7 min readUpdated
On this page

Basic tables need only <tr>, <th> and <td>. Real-world tables also need a title, separate header and body sections, and cells that cover more than one row or column.

All examples in this lesson use the same small style block for borders, shown in the first example.

A caption#

<caption> gives the table a title. It must be the first element inside <table>:

HTML
<style>
  table { border-collapse: collapse; }
  th, td { border: 1px solid #999; padding: 6px 12px; }
</style>
<table>
  <caption>Monthly bus pass prices</caption>
  <tr><th>Pass</th><th>Price (₹)</th></tr>
  <tr><td>Student</td><td>400</td></tr>
  <tr><td>General</td><td>1,050</td></tr>
</table>
Result

Screen readers announce the caption when users reach the table, so they know what it contains before hearing any cells.

thead, tbody and tfoot#

These elements split the rows into a header, a body and a footer:

HTML
<style>
  table { border-collapse: collapse; }
  th, td { border: 1px solid #999; padding: 6px 12px; }
  tfoot { font-weight: bold; }
</style>
<table>
  <caption>Shopping bill</caption>
  <thead>
    <tr><th>Item</th><th>Qty</th><th>Amount (₹)</th></tr>
  </thead>
  <tbody>
    <tr><td>Rice (5 kg)</td><td>1</td><td>350</td></tr>
    <tr><td>Milk (1 L)</td><td>2</td><td>130</td></tr>
  </tbody>
  <tfoot>
    <tr><td>Total</td><td></td><td>480</td></tr>
  </tfoot>
</table>
Result
  • <thead> holds the heading row(s).
  • <tbody> holds the data rows. A table can have several <tbody> groups.
  • <tfoot> holds summary rows such as totals.

They make the structure clear, let you style each part separately, and allow browsers to repeat the header on every page when a long table is printed.

Merging cells: colspan and rowspan#

colspan makes a cell span several columns; rowspan makes it span several rows:

HTML
<style>
  table { border-collapse: collapse; }
  th, td { border: 1px solid #999; padding: 6px 12px; text-align: center; }
</style>
<table>
  <caption>College timetable</caption>
  <tr><th>Time</th><th>Monday</th><th>Tuesday</th></tr>
  <tr><th>9:00</th><td>Maths</td><td rowspan="2">Lab (2 hours)</td></tr>
  <tr><th>10:00</th><td>Physics</td></tr>
  <tr><th>11:00</th><td colspan="2">Sports for everyone</td></tr>
</table>
Result

When a cell spans rows, leave out the cell it covers in the rows below. The 10:00 row above has only two cells because "Lab" already fills its Tuesday slot. Counting carefully is the hardest part of spanning; draw the grid on paper if needed.

The scope attribute#

scope tells assistive technology whether a <th> is the heading for a column or a row:

HTML
<table>
  <tr>
    <th scope="col">City</th>
    <th scope="col">Population</th>
  </tr>
  <tr>
    <th scope="row">Mumbai</th>
    <td>12.4 million (2011 census)</td>
  </tr>
</table>

For simple tables, browsers usually work this out themselves, but adding scope is a good habit and is important in tables that have both row and column headers.

Styling columns: colgroup and col#

<colgroup> and <col> let you style whole columns, for example their width or background:

HTML
<style>
  table { border-collapse: collapse; }
  th, td { border: 1px solid #999; padding: 6px 12px; }
</style>
<table>
  <colgroup>
    <col>
    <col style="background: #fff3c4">
  </colgroup>
  <tr><th>Plan</th><th>Price</th></tr>
  <tr><td>Basic</td><td>Free</td></tr>
  <tr><td>Pro</td><td>₹299/month</td></tr>
</table>
Result

Only a few CSS properties work on <col>: mainly background, border, width and visibility.

Practice#

Practice exercise

Build a table with the caption "Exam results", a <thead> with columns Name, Maths and Science, two students in <tbody>, and a <tfoot> row labelled "Class average" with the average mark for each subject.

Show solution
HTML
<style>
  table { border-collapse: collapse; }
  th, td { border: 1px solid #999; padding: 6px 12px; }
</style>
<table>
  <caption>Exam results</caption>
  <thead>
    <tr><th scope="col">Name</th><th scope="col">Maths</th><th scope="col">Science</th></tr>
  </thead>
  <tbody>
    <tr><th scope="row">Asha</th><td>92</td><td>85</td></tr>
    <tr><th scope="row">Ravi</th><td>78</td><td>91</td></tr>
  </tbody>
  <tfoot>
    <tr><th scope="row">Class average</th><td>85</td><td>88</td></tr>
  </tfoot>
</table>
Result

Key takeaway#

Finished this lesson?