Home / Snippets / UI Components /

Stat/metric card

Dashboard KPI card with large number, label, and colored trend arrow.

Revenue
$48.2k
↑ 12.5%
Users
3,842
↓ 3.1%
Uptime
99.9%
— 0.0%
Widely Supported
uino-js

Quick implementation

/* HTML:
<div class="stat-card">
  <div class="stat-card-label">Revenue</div>
  <div class="stat-card-value">$48.2k</div>
  <div class="stat-card-trend stat-card-trend--up">↑ 12.5%</div>
</div>
*/

.stat-card {
  padding: 1.25rem;
  border-radius: 0.5rem;
  border: 1px solid oklch(0.3 0.02 260);
  background: oklch(0.19 0.02 260);
}

.stat-card-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: oklch(0.63 0.02 260);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.stat-card-value {
  font-size: 2rem;
  font-weight: 800;
  color: oklch(0.93 0.01 260);
  line-height: 1.2;
  margin-top: 0.25rem;
}

.stat-card-trend {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.8rem;
  font-weight: 600;
  margin-top: 0.5rem;
}

.stat-card-trend--up   { color: oklch(0.72 0.17 155); }
.stat-card-trend--down { color: oklch(0.68 0.19 25); }
.stat-card-trend--neutral { color: oklch(0.63 0.02 260); }

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are a senior frontend engineer building a dashboard component library.

Goal: A stat/metric card that displays a KPI value, label, and trend indicator with directional coloring — no JavaScript for styling.

Technical constraints:
- Card uses padding + border-radius, no fixed width (adapts to grid column).
- Value uses large display font (2rem+, font-weight 800) for at-a-glance scanning.
- Trend indicator uses green for up, red for down, muted for neutral — all in oklch().
- Trend arrow is a Unicode character (↑ ↓ —), not an icon font or SVG.
- Use oklch() for all color values, not hex or rgba().
- Cards should work in a CSS Grid row with repeat(auto-fit, minmax(12rem, 1fr)).

Framework variant (pick one):
A) Vanilla HTML + CSS only.
B) React component — accept label (string), value (string), trend (number), and optional format (currency | percent | number) props.

Edge cases to handle:
- Very large numbers: value should not overflow or wrap awkwardly.
- Trend of exactly 0: show neutral style, not up or down.
- Screen readers: trend arrow needs an aria-label like "Up 12.5%".
- Dark mode: green/red must meet 3:1 contrast against the card background.

Return HTML + CSS.

Why this matters in 2026

Every dashboard needs stat cards. The pattern is deceptively simple — a number, a label, a trend — but getting the typography hierarchy, trend colors, and responsive sizing right without a component library takes care. This snippet gives you a production-ready card that works in any grid, uses oklch() for perceptually consistent trend colors, and scales from mobile to widescreen dashboards.

The logic

The card is a simple block with no fixed width — it fills whatever grid column it's placed in. The value uses a large display font with font-weight: 800 for instant visual hierarchy. The trend indicator uses three modifier classes: --up (green at hue 155), --down (red at hue 25), and --neutral (muted gray). Using oklch() ensures the green and red have equal perceived brightness, so neither dominates visually. The arrow characters (↑ ↓ —) are plain Unicode, avoiding icon font dependencies.

Accessibility & performance

Color alone must not convey the trend direction — the arrow character (↑ ↓) provides a shape cue, and an aria-label on the trend element provides the full context ("Up 12.5%"). The green and red values are chosen to meet WCAG 3:1 contrast against the dark card background. For users with color vision deficiency, the arrow direction is the primary indicator. Performance is trivial — no animations, no layout complexity, just styled text in a box.