CSS Table Styling
CSS Table Styling
Tables communicate relationships between rows and columns; CSS should improve that structure without discarding the semantics.
What you’ll learn
- Style semantic table headings and cells.
- Compare borders, spacing and zebra stripes.
- Make large tables scroll safely on narrow screens.
Understand the concept
A table uses <caption>, <thead>, <tbody>, and proper <th scope="col"> headers. Use border-collapse for clean lines, padding for readable cells, and tbody tr:nth-child(even) for alternating rows.
Wrap a wide table in a container with overflow-x:auto rather than forcing tiny text or changing data-table semantics.
What the browser evaluates
Padding affects cell readability; collapsed borders avoid double edges; nth-child colors rows by position; an overflow container preserves table columns.
Borders and readable cells
Start with semantic headings and cell spacing.
HTML
<div class="table-wrap"><table><caption>Fruit prices</caption><thead><tr><th scope="col">Fruit</th><th scope="col">Price</th></tr></thead><tbody><tr><td>Apple</td><td>$3.00</td></tr><tr><td>Banana</td><td>$1.50</td></tr><tr><td>Orange</td><td>$2.00</td></tr></tbody></table></div>CSS
.table-wrap { overflow-x: auto; } .table-wrap table { width: 100%; border-collapse: collapse; } .table-wrap caption { text-align: left; margin-bottom: 8px; font-weight: 700; } .table-wrap th, .table-wrap td { border: 1px solid #94a3b8; text-align: left; padding: 10px; }Rendered output
| Fruit | Price |
|---|---|
| Apple | $3.00 |
| Banana | $1.50 |
| Orange | $2.00 |
Observe: The header labels identify columns, and collapsed cell borders form single lines.
Zebra stripes and hover
Add a distinct header, alternating rows and responsive overflow.
HTML
<div class="table-wrap"><table><caption>Fruit prices</caption><thead><tr><th scope="col">Fruit</th><th scope="col">Price</th></tr></thead><tbody><tr><td>Apple</td><td>$3.00</td></tr><tr><td>Banana</td><td>$1.50</td></tr><tr><td>Orange</td><td>$2.00</td></tr></tbody></table></div>CSS
.table-wrap { overflow-x: auto; } .table-wrap table { width: 100%; min-width: 240px; border-collapse: collapse; } .table-wrap caption { text-align: left; margin-bottom: 8px; font-weight: 700; } .table-wrap th, .table-wrap td { border-bottom: 1px solid #cbd5e1; text-align: left; padding: 12px; } .table-wrap thead { background: #1d4ed8; color: white; } .table-wrap tbody tr:nth-child(even) { background: #eff6ff; } .table-wrap tbody tr:hover { background: #ccfbf1; }Rendered output
| Fruit | Price |
|---|---|
| Apple | $3.00 |
| Banana | $1.50 |
| Orange | $2.00 |
Observe: The blue header and alternating rows improve scanning. On narrow widths, the wrapper scrolls.
Original CSS Table Styling — All Worked Examples
The original ProgramGuru table tutorial below is preserved with its progressive border, padding, striping, hover, header, alignment, responsive and complete-table demonstrations. This supplement retains the original source code and rendered output for each step.
HTML tables by default look basic and rigid. To create visually appealing, readable, and modern tables, CSS table styling is essential. Whether you're building a pricing chart, a data report, or a comparison table, CSS helps you bring structure and beauty to your data.
Basic Table Structure
Before diving into styling, let’s take a basic HTML table with three columns and five rows.
<div class="table-container">
<table>
<thead>
<tr>
<th>Fruit</th>
<th>Color</th>
<th>Price (per kg)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>Red</td>
<td>$3.00</td>
</tr>
<tr>
<td>Banana</td>
<td>Yellow</td>
<td>$1.50</td>
</tr>
<tr>
<td>Grapes</td>
<td>Purple</td>
<td>$2.80</td>
</tr>
<tr>
<td>Orange</td>
<td>Orange</td>
<td>$2.00</td>
</tr>
<tr>
<td>Watermelon</td>
<td>Green</td>
<td>$0.90</td>
</tr>
</tbody>
</table>
</div>
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
1. Adding Basic Borders
Let’s start by giving the table a clean border using CSS:
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
Explanation: The border-collapse: collapse; property ensures that adjacent borders don’t double up — they merge into a single clean line.
2. Adding Padding and Spacing
To make text more readable, add padding to cells:
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
This increases whitespace within cells, enhancing clarity.
3. Zebra Striping Rows
Alternating row colors (also known as zebra striping) improve readability across rows of data.
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
}
tbody tr:nth-child(even) {
background-color: #f2f2f2;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
This subtle visual cue helps users follow data rows horizontally with ease.
4. Hover Effects for Interactivity
You can add a hover effect to highlight rows dynamically:
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
}
tbody tr:hover {
background-color: #e0e0e0;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
Users get feedback when they hover over a row — especially useful for clickable rows or admin dashboards.
5. Styling Headers
Headers can stand out using background color and text styling:
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
}
thead th {
background-color: #4CAF50;
color: white;
font-weight: bold;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
This helps distinguish headers from the rest of the table data visually and semantically.
6. Aligning Text
Column-wise alignment enhances data interpretation:
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
}
td:nth-child(2) {
text-align: center;
}
td:nth-child(3) {
text-align: right;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
This is particularly helpful for numbers, prices, and data meant to be compared vertically.
7. Responsive Table Design
Standard tables are not mobile-friendly by default. Use the following approach for better responsiveness:
.table-container {
overflow-x: auto;
}
<div class="table-container">
<table>...</table>
</div>
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
This ensures your tables can be scrolled horizontally on smaller screens.
8. Table Width and Layout
Control table width and column behavior using:
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
table {
width: 100%;
table-layout: fixed;
}
th, td {
word-wrap: break-word;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
table-layout: fixed forces columns to distribute width evenly, preventing overflow issues.
9. Borderless Tables
To create a minimalist look:
table {
border: none;
}
th, td {
border: none;
padding: 10px;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
Use this for simple data listings where structure clarity isn’t critical.
10. Table with Complete Styling - 1
.table-container {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
thead th {
background-color: #007BFF;
color: white;
}
th, td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
}
tbody tr:nth-child(even) {
background-color: #f9f9f9;
}
tbody tr:hover {
background-color: #f1f1f1;
}
| Fruit | Color | Price (per kg) |
|---|---|---|
| Apple | Red | $3.00 |
| Banana | Yellow | $1.50 |
| Grapes | Purple | $2.80 |
| Orange | Orange | $2.00 |
| Watermelon | Green | $0.90 |
Explain the result
Padding affects cell readability; collapsed borders avoid double edges; nth-child colors rows by position; an overflow container preserves table columns.
Compare the two examples: identify the selector, each changed property, and which visible part of the output proves that the CSS took effect.
Common mistakes to avoid
Never remove table headers just to make the layout look like separate cards.
Zebra striping should support—not replace—clear borders and typography.
Try it yourself
Add a third column and test the table at a 320px viewport; confirm that only the table wrapper scrolls.
Before changing the code, predict what will change. Then verify by checking the rendered result.
Check your understanding
What you should remember
Preserve table semantics while improving alignment, hierarchy, and responsive readability.
Revisit the rendered examples if the rule still feels abstract. Change one declaration at a time so you can connect cause and effect.
Reaching the recap and completing the quizzes are separate milestones.