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>