HTML Tables
1. Introduction
HTML tables are designed for one specific purpose: displaying tabular data โ information that has a natural row-and-column structure with relationships between cells and headers. Understanding how to build accessible, well-structured tables โ and knowing when not to use them โ is an essential HTML skill. This lesson covers the complete table element set and best practices for data tables.
2. Concept
Table Element Hierarchy
| Element | Role | Where It Goes |
|---|---|---|
<table> |
Root container | Wraps everything |
<caption> |
Accessible title | First child of table |
<thead> |
Header row group | Before tbody |
<tbody> |
Data row group | Main table body |
<tfoot> |
Footer row group | After tbody |
<tr> |
Table row | Inside thead/tbody/tfoot |
<th> |
Header cell | Inside tr (usually thead) |
<td> |
Data cell | Inside tr (tbody) |
<th> for header cells, not <td> with bold styling. The <th> element has semantic meaning โ it defines a header for a column or row โ and screen readers use it to provide context for data cells.scope="col" to column headers and scope="row" to row headers. This explicitly links each header to its respective column or row for screen readers.3. Basic Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tables Demo</title>
</head>
<body>
<table>
<caption>Q1 2025 Sales by Region</caption>
<thead>
<tr>
<th scope="col">Region</th>
<th scope="col">January</th>
<th scope="col">February</th>
<th scope="col">March</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">North</th>
<td>ยฃ12,400</td>
<td>ยฃ14,100</td>
<td>ยฃ16,250</td>
</tr>
<tr>
<th scope="row">South</th>
<td>ยฃ9,800</td>
<td>ยฃ11,500</td>
<td>ยฃ13,000</td>
</tr>
<tr>
<th scope="row">East</th>
<td>ยฃ7,600</td>
<td>ยฃ8,200</td>
<td>ยฃ9,750</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">Total</th>
<td>ยฃ29,800</td>
<td>ยฃ33,800</td>
<td>ยฃ39,000</td>
</tr>
</tfoot>
</table>
</body>
</html>
4. How It Works
Step 1 โ caption Provides Context
<caption> is the table’s accessible title. Screen readers announce it before reading cell data, giving users the context they need.
Step 2 โ thead, tbody, tfoot Semantics
These grouping elements allow browsers to treat header and footer rows differently (e.g., repeat headers on each printed page). They also make the table structure machine-readable.
Step 3 โ scope Attribute on th
scope="col" declares that a header applies to all cells in its column. scope="row" declares it applies to all cells in its row. This is crucial for complex tables where screen readers must associate a cell with the correct header.
Step 4 โ colspan and rowspan
Use colspan="2" on a <td> to make it span two columns. Use rowspan="3" to span three rows. Remember to reduce the cell count in the affected rows/columns accordingly.
5. Real-World Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hosting Plans Comparison</title>
</head>
<body>
<h1>Hosting Plans Comparison</h1>
<table>
<caption>Comparison of Starter, Pro, and Enterprise hosting plans</caption>
<thead>
<tr>
<th scope="col">Feature</th>
<th scope="col">Starter</th>
<th scope="col">Pro</th>
<th scope="col">Enterprise</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Monthly Price</th>
<td>$5</td><td>$20</td><td>$99</td>
</tr>
<tr>
<th scope="row">Storage</th>
<td>10 GB</td><td>100 GB</td><td>Unlimited</td>
</tr>
<tr>
<th scope="row">Domains</th>
<td>1</td><td>10</td><td>Unlimited</td>
</tr>
<tr>
<th scope="row">SSL Certificate</th>
<td>Free</td><td>Free</td><td>Free</td>
</tr>
<tr>
<th scope="row">Support</th>
<td>Email only</td><td>Email + Chat</td><td>Dedicated Manager</td>
</tr>
<tr>
<th scope="row">Backups</th>
<td colspan="2">Weekly</td>
<td>Daily</td>
</tr>
</tbody>
</table>
</body>
</html>
6. Common Mistakes
❌ Using td for header cells
<tr>
<td><strong>Name</strong></td>
<td><strong>Age</strong></td>
</tr>
✓ Use th with scope for header cells
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
</tr>
❌ Missing caption on data tables
<table>
<thead><tr><th>Item</th><th>Price</th></tr></thead>
</table>
✓ Add a caption for accessibility and context
<table>
<caption>Product pricing for Q1 2025</caption>
<thead><tr><th scope="col">Item</th><th scope="col">Price</th></tr></thead>
</table>
7. Try It Yourself
8. Quick Reference
| Element / Attribute | Purpose | Notes |
|---|---|---|
<table> |
Table container | Use only for tabular data |
<caption> |
Accessible table title | First child of table |
<thead> / <tbody> / <tfoot> |
Row group semantics | Improves structure and printing |
<th scope="col"> |
Column header cell | Screen reader association |
<th scope="row"> |
Row header cell | Screen reader association |
colspan |
Span multiple columns | Reduce cell count in that row |
rowspan |
Span multiple rows | Reduce cell count in spanned rows |