Tables & Data
Table Structure (table, tr, td, th)
Master HTML tables for organizing tabular data. Learn table structure, semantic elements, and how to create accessible data tables.
When to Use Tables
✅ Use Tables For:
- Tabular data (spreadsheet-like)
- Pricing comparisons
- Schedules and calendars
- Statistics and results
- Data reports
⌠Don't Use Tables For:
- Page layout (use CSS Grid/Flexbox)
- Navigation menus
- Image galleries
- Any non-tabular content
Basic Table Structure
HTML
<table>
<tr> <!-- Table Row -->
<th>Header 1</th> <!-- Table Header -->
<th>Header 2</th>
<th>Header 3</th>
</tr>
<tr>
<td>Data 1</td> <!-- Table Data -->
<td>Data 2</td>
<td>Data 3</td>
</tr>
<tr>
<td>Data 4</td>
<td>Data 5</td>
<td>Data 6</td>
</tr>
</table>Key Elements:
<table>- Container for the entire table<tr>- Table row (horizontal)<th>- Table header cell (bold, centered by default)<td>- Table data cell
Complete Table Example
HTML
<table>
<tr>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
<tr>
<td>John Doe</td>
<td>28</td>
<td>New York</td>
</tr>
<tr>
<td>Jane Smith</td>
<td>34</td>
<td>Los Angeles</td>
</tr>
<tr>
<td>Bob Johnson</td>
<td>45</td>
<td>Chicago</td>
</tr>
</table>Table Sections
Organize tables into semantic sections for better structure and styling:
HTML
<table>
<thead> <!-- Table Head -->
<tr>
<th>Product</th>
<th>Price</th>
<th>Stock</th>
</tr>
</thead>
<tbody> <!-- Table Body -->
<tr>
<td>Laptop</td>
<td>$999</td>
<td>15</td>
</tr>
<tr>
<td>Mouse</td>
<td>$25</td>
<td>150</td>
</tr>
<tr>
<td>Keyboard</td>
<td>$75</td>
<td>80</td>
</tr>
</tbody>
<tfoot> <!-- Table Footer -->
<tr>
<th>Total Items</th>
<td colspan="2">245</td>
</tr>
</tfoot>
</table>Benefits of Sections:
- Semantic structure for accessibility
- Easier CSS targeting
- Header/footer can repeat on printed pages
- Better for screen readers
Table Caption
Provide a title/description for the table:
HTML
<table>
<caption>Monthly Sales Report - Q4 2024</caption>
<thead>
<tr>
<th>Month</th>
<th>Sales</th>
<th>Growth</th>
</tr>
</thead>
<tbody>
<tr>
<td>October</td>
<td>$45,000</td>
<td>+12%</td>
</tr>
<tr>
<td>November</td>
<td>$52,000</td>
<td>+15%</td>
</tr>
<tr>
<td>December</td>
<td>$68,000</td>
<td>+31%</td>
</tr>
</tbody>
</table>
<!-- Caption styling -->
<style>
caption {
font-weight: bold;
font-size: 1.2em;
margin-bottom: 0.5em;
caption-side: top; /* or bottom */
}
</style>Table Headers (Scope)
Use scope attribute to clarify header relationships:
HTML
<table>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Q1</th>
<th scope="col">Q2</th>
<th scope="col">Q3</th>
<th scope="col">Q4</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Laptops</th>
<td>150</td>
<td>180</td>
<td>210</td>
<td>190</td>
</tr>
<tr>
<th scope="row">Tablets</th>
<td>90</td>
<td>95</td>
<td>110</td>
<td>105</td>
</tr>
</tbody>
</table>
<!-- scope values: -->
<!-- col: Header for column -->
<!-- row: Header for row -->
<!-- colgroup: Header for group of columns -->
<!-- rowgroup: Header for group of rows -->Styling Tables
Basic Styling
HTML
<style>
table {
border-collapse: collapse; /* Removes space between borders */
width: 100%;
max-width: 800px;
margin: 20px auto;
}
th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}
th {
background-color: #4CAF50;
color: white;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #f2f2f2; /* Zebra striping */
}
tr:hover {
background-color: #ddd; /* Highlight on hover */
}
</style>Border Styles
CSS
/* Collapsed borders (default recommended) */
table {
border-collapse: collapse;
}
/* Separated borders */
table {
border-collapse: separate;
border-spacing: 5px; /* Space between cells */
}
/* No borders */
table {
border: none;
}
th, td {
border: none;
}
/* Only horizontal borders */
th, td {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
/* Only vertical borders */
th, td {
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}Responsive Tables
Method 1: Horizontal Scroll
HTML
<div class="table-container">
<table>
<!-- Table content -->
</table>
</div>
<style>
.table-container {
overflow-x: auto;
-webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */
}
table {
min-width: 600px; /* Minimum table width */
}
</style>Method 2: Stacked on Mobile
HTML
<style>
@media screen and (max-width: 600px) {
table, thead, tbody, th, td, tr {
display: block;
}
thead tr {
display: none; /* Hide header row */
}
tr {
margin-bottom: 15px;
border: 1px solid #ddd;
}
td {
text-align: right;
padding-left: 50%;
position: relative;
}
td::before {
content: attr(data-label);
position: absolute;
left: 10px;
font-weight: bold;
}
}
</style>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="Name">John Doe</td>
<td data-label="Email">john@example.com</td>
<td data-label="Phone">555-0100</td>
</tr>
</tbody>
</table>Accessibility
Accessible Table Checklist:
- ✅ Use
<caption>for table title - ✅ Use
<th>for headers (not<td>) - ✅ Add
scopeattribute to headers - ✅ Use
<thead>,<tbody>,<tfoot> - ✅ Provide summary for complex tables
- ✅ Ensure sufficient color contrast
- ✅ Don't rely on color alone
Complex Table with IDs
HTML
<table>
<caption>Sales by Region and Product</caption>
<thead>
<tr>
<th id="region">Region</th>
<th id="product">Product</th>
<th id="sales">Sales</th>
</tr>
</thead>
<tbody>
<tr>
<td headers="region">North</td>
<td headers="product">Laptops</td>
<td headers="sales">$50,000</td>
</tr>
</tbody>
</table>Best Practices
✅ Do
- Use tables for tabular data only
- Include caption and headers
- Use scope attribute
- Use thead, tbody, tfoot
- Make tables responsive
- Style for readability
- Test with screen readers
- Use border-collapse: collapse
⌠Don't
- Use tables for layout
- Forget accessibility
- Make tables too wide
- Use only for visual design
- Forget mobile users
- Use
<td>for headers - Nest tables unnecessarily
- Forget caption element
Complete Example
HTML
<table>
<caption>Employee Directory - IT Department</caption>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Position</th>
<th scope="col">Email</th>
<th scope="col">Extension</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Alice Johnson</th>
<td>Senior Developer</td>
<td>alice@company.com</td>
<td>x4501</td>
</tr>
<tr>
<th scope="row">Bob Smith</th>
<td>DevOps Engineer</td>
<td>bob@company.com</td>
<td>x4502</td>
</tr>
<tr>
<th scope="row">Carol White</th>
<td>QA Manager</td>
<td>carol@company.com</td>
<td>x4503</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row" colspan="3">Total Employees</th>
<td>3</td>
</tr>
</tfoot>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
max-width: 900px;
margin: 20px auto;
font-family: Arial, sans-serif;
}
caption {
font-size: 1.5em;
font-weight: bold;
margin-bottom: 10px;
color: #333;
}
thead {
background-color: #2c3e50;
color: white;
}
th, td {
padding: 12px 15px;
text-align: left;
border: 1px solid #ddd;
}
tbody tr:nth-child(even) {
background-color: #f8f9fa;
}
tbody tr:hover {
background-color: #e9ecef;
}
tfoot {
font-weight: bold;
background-color: #ecf0f1;
}
@media screen and (max-width: 600px) {
table {
font-size: 14px;
}
th, td {
padding: 8px;
}
}
</style>