HTML Tables
Tables organize data into rows and columns. Use them for tabular data — not for page layout.
Basic Table Structure
Every table follows this structure:
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>25</td>
<td>Cairo</td>
</tr>
<tr>
<td>Bob</td>
<td>30</td>
<td>Alexandria</td>
</tr>
</tbody>
</table>
Table Elements
<table>— Wraps the entire table<thead>— Groups header rows<tbody>— Groups body rows<tfoot>— Groups footer rows (optional)<tr>— Table row<th>— Header cell (bold, centered by default)<td>— Data cell
Table Headers
Headers define what each column represents:
<table>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Price</th>
<th scope="col">Quantity</th>
</tr>
</thead>
<tbody>
<tr>
<td>Laptop</td>
<td>$999</td>
<td>5</td>
</tr>
</tbody>
</table>
The scope attribute helps screen readers understand header relationships.
Row Headers
Headers can also define row categories:
<table>
<thead>
<tr>
<th></th>
<th scope="col">Monday</th>
<th scope="col">Tuesday</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Morning</th>
<td>Meeting</td>
<td>Coding</td>
</tr>
<tr>
<th scope="row">Afternoon</th>
<td>Design</td>
<td>Testing</td>
</tr>
</tbody>
</table>
Spans
Cells can span multiple columns or rows:
<table>
<thead>
<tr>
<th colspan="3">Quarterly Sales Report</th>
</tr>
<tr>
<th>Product</th>
<th>Q1</th>
<th>Q2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Laptops</td>
<td>150</td>
<td>200</td>
</tr>
<tr>
<td colspan="2">Total Units</td>
<td>350</td>
</tr>
</tbody>
</table>
Attributes:
colspan— Spans multiple columnsrowspan— Spans multiple rows
Caption
Add a caption to describe the table:
<table>
<caption>Employee Directory</caption>
<thead>
<tr>
<th>Name</th>
<th>Department</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>Engineering</td>
</tr>
</tbody>
</table>
Accessibility
Proper table structure helps screen readers:
<table aria-label="User statistics">
<thead>
<tr>
<th scope="col">Username</th>
<th scope="col">Posts</th>
<th scope="col">Followers</th>
</tr>
</thead>
<tbody>
<tr>
<td>@alice</td>
<td>142</td>
<td>1,234</td>
</tr>
<tr>
<td>@bob</td>
<td>89</td>
<td>567</td>
</tr>
</tbody>
</table>
Styling Tables
Basic CSS for readable tables:
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
border: 1px solid #ddd;
padding: 8px 12px;
text-align: left;
}
th {
background-color: #f5f5f5;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
Complete Example
Here’s a complete, styled table:
<table aria-label="Course catalog">
<caption>
<h2>Web Development Courses</h2>
</caption>
<thead>
<tr>
<th scope="col">Course</th>
<th scope="col">Level</th>
<th scope="col">Duration</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>HTML Basics</td>
<td>Beginner</td>
<td>2 hours</td>
<td>Free</td>
</tr>
<tr>
<td>CSS Fundamentals</td>
<td>Beginner</td>
<td>3 hours</td>
<td>Free</td>
</tr>
<tr>
<td>JavaScript Mastery</td>
<td>Intermediate</td>
<td>8 hours</td>
<td>$49</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">Total Courses</td>
<td>3</td>
</tr>
</tfoot>
</table>
When NOT to Use Tables
Use tables for:
- Tabular data (spreadsheets, schedules, comparison charts)
- Data that needs rows and columns
Don’t use tables for:
- Page layout (use CSS Flexbox/Grid)
- Forms (use form elements)
- Visual arrangement of elements
Common Mistakes
- Using tables for layout — Bad for accessibility and maintenance
- Missing headers — Screen readers can’t navigate properly
- No scope attribute — Headers lose their relationship
- Nested tables — Avoid nesting tables inside tables
- Missing caption — Tables need context for accessibility