CSS Tutorial
CSS Tables
border-collapse, padding on th/td, and zebra stripes make a data table readable.
Unstyled tables look sparse
A raw <table> has thin or missing borders, cramped cells, and header text that does not stand apart from the numbers. CSS is what makes a Harbor studio firing log readable: collapse the grid, pad the cells, and stripe the rows.
Style th and td, not only table. Borders on the table element alone do not draw the inner grid. Caption, header, and body stay in the HTML; color and space stay in the stylesheet.
Example
<style>
table {
width: 100%;
border-collapse: collapse;
color: #0c4a6e;
}
th, td {
border: 1px solid #7dd3fc;
padding: 8px 12px;
text-align: left;
}
th {
background: teal;
color: white;
}
</style>
<table>
<caption>Harbor studio kiln log</caption>
<thead>
<tr><th>Day</th><th>Firing</th><th>°C</th></tr>
</thead>
<tbody>
<tr><td>Tue</td><td>Bisque</td><td>950</td></tr>
<tr><td>Thu</td><td>Glaze</td><td>1220</td></tr>
</tbody>
</table>border-collapse
border-collapse: separate (the default) draws each cell with its own border and a gap controlled by border-spacing. Double lines appear where two cells meet.border-collapse: collapse merges adjoining borders into one line. Collapsed tables are the usual look for data.
| Value | Result |
|---|---|
collapse | One shared grid line |
separate | Each cell keeps its own border |
Example
<style>
.apart {
border-collapse: separate;
border-spacing: 8px;
color: #0c4a6e;
}
.apart th,
.apart td {
border: 2px solid teal;
padding: 8px;
background: #e0f2fe;
}
</style>
<table class="apart">
<tr><th>Slip</th><th>Status</th></tr>
<tr><td>A12</td><td>Ready</td></tr>
<tr><td>B04</td><td>Firing</td></tr>
</table>border-spacing only applies when borders are separate. It is ignored on a collapsed table. Use cell padding for air inside collapsed grids.
Padding on th and td
Numbers jammed against a border are hard to scan. Put padding on the cells, not on the table. Horizontal padding of 12 pixels and vertical padding of 8 is a solid Harbor studio default. Align numbers to the right when you compare them down a column; keep labels left.
Example
<style>
table {
border-collapse: collapse;
color: #0c4a6e;
}
th, td {
padding: 8px 12px;
border-bottom: 1px solid #bae6fd;
}
td:last-child {
text-align: right;
font-variant-numeric: tabular-nums;
}
th {
text-align: left;
background: #f0f9ff;
}
</style>
<table>
<tr><th>Item</th><th>Price</th></tr>
<tr><td>Clay bag</td><td>18</td></tr>
<tr><td>Glaze pint</td><td>12</td></tr>
</table>font-variant-numeric: tabular-nums uses equal-width digits so 950 and 1220 line up. Open the example in /css/try and add a third row to see the column stay steady.
Zebra stripes with nth-child
Alternating row colors help the eye track across a wide table. tbody tr:nth-child(even)(or odd) paints every other data row. Keep contrast gentle — a sky wash, not a second loud fill — so the teal header still wins as the landmark.
Example
<style>
table {
border-collapse: collapse;
width: 100%;
color: #0c4a6e;
}
th, td {
padding: 8px 12px;
border-bottom: 1px solid #e0f2fe;
}
th {
background: teal;
color: white;
text-align: left;
}
tbody tr:nth-child(even) {
background: #f0f9ff;
}
tbody tr:hover {
background: #ccfbf1;
}
caption {
text-align: left;
margin-bottom: 8px;
color: #0f766e;
font-weight: 700;
}
</style>
<table>
<caption>Harbor studio bookings</caption>
<thead>
<tr><th>Name</th><th>Slot</th></tr>
</thead>
<tbody>
<tr><td>Ada</td><td>08:00</td></tr>
<tr><td>Linus</td><td>10:00</td></tr>
<tr><td>Grace</td><td>13:00</td></tr>
<tr><td>Niels</td><td>15:00</td></tr>
</tbody>
</table>Hover color is extra, not a substitute for a focus style on interactive cells. If a row is a link, keep :focus visible on the link itself.
Width, caption, and empty cells
table { width: 100%; } lets the grid fill its parent. Pair it withmax-width on a wrapper if the line of numbers gets too long. Stylecaption as a heading above the grid. Empty cells still need padding so the row height matches its neighbors.
Next: icons. Small SVG marks sit in table cells and buttons without breaking the grid you just padded.
Worked examples
The short listings above show one property. These sheets paint documents you would actually ship: a lab dashboard, a clinic form, a marks table, a nav bar.
CSS does not invent meaning. HTML already said what the pieces are. Cascade, specificity, and the box model decide how they look. The numbers are classroom values — current, pH, pulse, 3-4-5 — so the style has something real to sit on.
Preview them in the CSS editor at /css/try. Change one property and watch the page paint. The tags stay the same.
Statistics
Collapsed borders and zebra rows
border-collapse: collapse shares one line between cells. Separate is the old double-line look. Padding on th/td is what makes numbers readable.
nth-child(odd) is a zebra. Caption sits with the table. This is a marks sheet, not a layout grid.
mean = (Σ xᵢ) / n
Example
<style>
table { border-collapse: collapse; }
th, td { border: 1px solid #7dd3fc; padding: 0.35rem 0.6rem; }
th { background: #e0f2fe; }
tr:nth-child(even) td { background: #f8fafc; }
</style>
<table>
<caption>Physics test</caption>
<tr><th>Name</th><th>Mark</th></tr>
<tr><td>Ada</td><td>72</td></tr>
<tr><td>Ben</td><td>81</td></tr>
</table>Chemistry
A titre table you can scan
Right-align numbers in real work (text-align: right on td). Headers stay left. That is how a burette column is read.
Example
<style>
td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
th, td { padding: 0.4rem 0.7rem; }
</style>
<table>
<tr><th>Run</th><th>mL</th></tr>
<tr><td>1</td><td>24.8</td></tr>
<tr><td>2</td><td>25.1</td></tr>
</table>