CSS Tutorial
CSS Project: Dashboard Cards
A small stats dashboard: four metric cards on a grid, with a muted header and numeric emphasis.
What you will build
A morning board for Harbor studio. A muted header names the day. Four metric cards sit on a grid: tables booked, loaves out, prints on the line, and espresso pulled. The numbers are the loudest type. Labels stay small and quiet.
CSS variables hold the sky palette so every card shares ink, paper, and accent. Change one custom property and the board shifts together.
Open an example with Try it in CSS. That loads /css/try — a live page preview.
Properties you will use
| Property | Job on this page |
|---|---|
display: grid | Lays four metric cards in a responsive row |
CSS variables (--ink, --accent) | Keeps the harbor palette in one place |
font-size / font-weight | Makes the number dominate the card |
letter-spacing | Quiets the header and the metric labels |
gap | Even space between cards |
The numbers are text in p or data, not images. If you need to change 12 to 13, you edit a digit, not a graphic.
Build in slices
First the palette and one metric card. The label is small. The figure is large. Variables live on:root.
Example
<style>
:root {
--ink: #0c4a6e;
--paper: #e0f2fe;
--card: #fff;
--accent: #0284c7;
--muted: #075985;
}
body {
font-family: system-ui, sans-serif;
background: var(--paper);
color: var(--ink);
margin: 1.5rem;
}
.metric {
background: var(--card);
border-radius: 1rem;
padding: 1.1rem 1.15rem 1.2rem;
box-shadow: 0 10px 22px rgba(12, 74, 110, 0.1);
}
.label {
margin: 0;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--muted);
}
.figure {
margin: 0.25rem 0 0;
font-size: 2.4rem;
font-weight: 800;
color: var(--accent);
line-height: 1.1;
}
</style>
<article class="metric">
<p class="label">Tables booked</p>
<p class="figure">12</p>
</article>Then place four cards on a grid with a muted page header. auto-fit drops to two columns, then one, as the window narrows.
Example
<style>
.board-head {
margin-bottom: 1.1rem;
}
.board-head p {
margin: 0;
font-size: 0.78rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
}
.board-head h1 { margin: 0.2rem 0 0; font-size: 1.45rem; }
.metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
gap: 1rem;
}
</style>
<header class="board-head">
<p>Saturday morning</p>
<h1>Harbor studio board</h1>
</header>Change --accent once at /css/try. Every figure should follow. If one number stays navy, that card hardcoded a color.
Complete page
Four real metrics and a quiet header. The complete stylesheet keeps variables at the top so you can retint the board without hunting through rules.
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Harbor studio — morning board</title>
<style>
:root {
--ink: #0c4a6e;
--paper: #e0f2fe;
--card: #fff;
--accent: #0284c7;
--muted: #075985;
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
background: var(--paper);
color: var(--ink);
font-family: system-ui, sans-serif;
padding: 2rem 1.25rem;
}
.wrap { max-width: 52rem; margin: 0 auto; }
.board-head { margin-bottom: 1.2rem; }
.board-head p {
margin: 0;
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
}
.board-head h1 {
margin: 0.25rem 0 0;
font-size: 1.55rem;
}
.metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
gap: 1rem;
}
.metric {
background: var(--card);
border-radius: 1rem;
padding: 1.15rem 1.15rem 1.25rem;
box-shadow: 0 10px 22px rgba(12, 74, 110, 0.1);
border-top: 4px solid var(--accent);
}
.label {
margin: 0;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--muted);
}
.figure {
margin: 0.3rem 0 0.15rem;
font-size: 2.45rem;
font-weight: 800;
color: var(--accent);
line-height: 1.05;
}
.hint {
margin: 0;
color: var(--muted);
font-size: 0.9rem;
}
</style>
</head>
<body>
<div class="wrap">
<header class="board-head">
<p>Saturday morning · 8–16</p>
<h1>Harbor studio board</h1>
</header>
<div class="metrics">
<article class="metric">
<p class="label">Tables booked</p>
<p class="figure">12</p>
<p class="hint">Window side full at 9:30</p>
</article>
<article class="metric">
<p class="label">Loaves out</p>
<p class="figure">28</p>
<p class="hint">Sourdough still on the rack</p>
</article>
<article class="metric">
<p class="label">Prints on the line</p>
<p class="figure">7</p>
<p class="hint">Menus dry by noon</p>
</article>
<article class="metric">
<p class="label">Espresso pulled</p>
<p class="figure">41</p>
<p class="hint">Cafe till 16:00</p>
</article>
</div>
</div>
</body>
</html>Practice tasks
- Set
--accentto#0c4a6e. Confirm every figure and top border follows. - Add a fifth metric for Guest passes. Check that the grid wraps instead of overflowing.
- Lower the figure size to
1.8remand decide if the cards still read as stats. Preview at /css/try.