Information on the web frequently needs to be organized into grids of rows and columns, similar to a spreadsheet. Think of a financial report, a product comparison chart, or a daily schedule. HTML provides a dedicated set of tags specifically for structuring this type of tabular data.
Building a table is like assembling blocks. You start with the main container, divide it into rows, and then chop those rows into individual cells.
<table>: The outer wrapper. Everything inside is part of the table grid.<tr> (Table Row): Acts as a horizontal slice across the table.<th> (Table Header): Special cells that act as titles for columns or rows. Browsers usually make these bold and centered automatically to make them stand out.<td> (Table Data): The standard cells where your actual content goes. These can hold entirely formatted HTML, not just text! (Images, links, or even nested tables).To see how these pieces fit together, let's create a simple scoreboard for a game.
<!-- The parent container -->
<table>
<!-- Row 1: The Headings -->
<tr>
<th>Player Name</th>
<th>Score</th>
<th>Status</th>
</tr>
<!-- Row 2: Data for Player 1 -->
<tr>
<td>Alice</td>
<td>2500</td>
<td>Active</td>
</tr>
<!-- Row 3: Data for Player 2 -->
<tr>
<td>Bob</td>
<td>1850</td>
<td>Eliminated</td>
</tr>
</table>
| Player Name | Score | Status |
|---|---|---|
| Alice | 2500 | Active |
| Bob | 1850 | Eliminated |
<td> and main content in another). This is a bad practice! Always use CSS for page layouts instead.
<td> and content in another was common in the 1990s. Use CSS Grid or Flexbox for layout — reserve <table> strictly for genuinely tabular data.
<th> for header cells. Using <td> for headers might look identical, but screen readers rely on <th> to announce which column/row a cell belongs to.
<thead>/<tbody>. Without them, assistive tech and CSS styling (like sticky headers) can't reliably distinguish header rows from data rows.
A second worked example, this time using colspan to merge cells for a lunch break row that spans every day:
<table>
<thead>
<tr>
<th>Time</th>
<th>Monday</th>
<th>Tuesday</th>
</tr>
</thead>
<tbody>
<tr>
<td>9:00</td>
<td>Math</td>
<td>Physics</td>
</tr>
<tr>
<td>12:00</td>
<td colspan="2">Lunch Break</td>
</tr>
</tbody>
</table>
Rendered result:
| Time | Monday | Tuesday |
|---|---|---|
| 9:00 | Math | Physics |
| 12:00 | Lunch Break | |
Q: Should I use tables for a page layout?
A: No — use CSS Grid or Flexbox instead. Tables should be reserved for actual tabular data.
Q: How do I make a table responsive on mobile?
A: Wrap it in a scrollable container like Bootstrap's .table-responsive, or restructure narrow tables into stacked cards at small screen widths with CSS.
Q: What's the difference between th and td?
A: <th> marks a header cell (bold, centered by default, and announced as a header by screen readers); <td> is a plain data cell. See the MDN <table> guide for the full element list.