15 / 20
All 20 in 20 CSS Minimalist UI
- 01Modular Type Scale with a Ratio Variable
- 02Type Hierarchy Without Any Color Change
- 03System Font Stack That Needs No Webfont
- 04Optical Alignment vs Mathematical Centering
- 05Spacing Scale from a Single Base Unit
- 06Whitespace That Groups Instead of Separates
- 07Vertical Rhythm with a Consistent Baseline
- 08Minimal Layout with CSS Grid and No Divs
- 09The One Accent Color Restraint Budget
- 10Grayscale Palette with Enough Contrast
- 11Borders and Dividers You Can Actually Remove
- 12Elevation Without Shadows or Gradients
- 13Why Minimal Interfaces Fail Accessibility
- 14Minimalist and Brutalist Side by Side
- 15Minimalist Dashboard Card and Metric
- 16Minimalist Product Card for Ecommerce
- 17Minimalist Portfolio Project Listing
- 18Minimalist Article Layout and Typography
- 19Minimalist Mobile App Screen in a Frame
- 20Minimalist Landing Page Section
Minimalist Dashboard Card and Metric
One metric card — value, label, delta and sparkline — where the hierarchy between the number and its label comes from scale and weight, not colour. A component study rather than a dashboard layout, so it drops into whatever grid you already have — and the delta carries a glyph and a word alongside its hue, so the direction survives for a reader who cannot resolve the colour.
Untitled UI Pro: a 10,000+ component Figma UI kit · from $129 one-time
Untitled UI · Affiliate link
The code
<section class="mu-15" aria-labelledby="mu-15-title">
<h2 class="mu-15__sr" id="mu-15-title">Account metrics</h2>
<div class="mu-15__theme">
<input class="mu-15__theme-input" type="checkbox" id="mu-15-theme">
<label class="mu-15__theme-label" for="mu-15-theme">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="mu-15__sr">Toggle dark theme</span>
</label>
</div>
<div class="mu-15__stage">
<div class="mu-15__grid">
<article class="mu-15__card" aria-labelledby="mu-15-m1">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m1">Monthly recurring revenue</h3>
<p class="mu-15__scope">Meridian · all regions</p>
</header>
<p class="mu-15__value">$281,440</p>
<p class="mu-15__delta mu-15__delta--up">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 19V5m0 0-6 6m6-6 6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>4.2%</b> <span>vs last month</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Twelve-month trend, rising from 214,000 to 281,440">
<path d="M0 52 20 49 40 51 60 44 80 46 100 38 120 34 140 36 160 27 180 22 200 24 220 14 240 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Updated 6 min ago</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
<article class="mu-15__card" aria-labelledby="mu-15-m2">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m2">Net revenue retention</h3>
<p class="mu-15__scope">Rolling 12 months</p>
</header>
<p class="mu-15__value">104.8%</p>
<p class="mu-15__delta mu-15__delta--down">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 5v14m0 0 6-6m-6 6-6-6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>0.6pt</b> <span>vs last quarter</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Rolling retention, flat then easing from 106.1 to 104.8 percent">
<path d="M0 22 20 20 40 24 60 21 80 26 100 24 120 29 140 27 160 33 180 31 200 36 220 34 240 39" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Cohort model v4</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
</div>
</div>
</section><section class="mu-15" aria-labelledby="mu-15-title">
<h2 class="mu-15__sr" id="mu-15-title">Account metrics</h2>
<div class="mu-15__theme">
<input class="mu-15__theme-input" type="checkbox" id="mu-15-theme">
<label class="mu-15__theme-label" for="mu-15-theme">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="mu-15__sr">Toggle dark theme</span>
</label>
</div>
<div class="mu-15__stage">
<div class="mu-15__grid">
<article class="mu-15__card" aria-labelledby="mu-15-m1">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m1">Monthly recurring revenue</h3>
<p class="mu-15__scope">Meridian · all regions</p>
</header>
<p class="mu-15__value">$281,440</p>
<p class="mu-15__delta mu-15__delta--up">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 19V5m0 0-6 6m6-6 6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>4.2%</b> <span>vs last month</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Twelve-month trend, rising from 214,000 to 281,440">
<path d="M0 52 20 49 40 51 60 44 80 46 100 38 120 34 140 36 160 27 180 22 200 24 220 14 240 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Updated 6 min ago</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
<article class="mu-15__card" aria-labelledby="mu-15-m2">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m2">Net revenue retention</h3>
<p class="mu-15__scope">Rolling 12 months</p>
</header>
<p class="mu-15__value">104.8%</p>
<p class="mu-15__delta mu-15__delta--down">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 5v14m0 0 6-6m-6 6-6-6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>0.6pt</b> <span>vs last quarter</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Rolling retention, flat then easing from 106.1 to 104.8 percent">
<path d="M0 22 20 20 40 24 60 21 80 26 100 24 120 29 140 27 160 33 180 31 200 36 220 34 240 39" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Cohort model v4</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
</div>
</div>
</section>.mu-15 {
--mu-15-value-size: clamp(2.25rem, 1.7rem + 2.4vw, 3rem);
--mu-15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
--mu-15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
position: relative;
box-sizing: border-box;
background: var(--mu-15-bg);
color: var(--mu-15-ink);
font-family: var(--mu-15-ui);
line-height: 1.5;
-webkit-text-size-adjust: 100%;
}
.mu-15 *,
.mu-15 *::before,
.mu-15 *::after {
box-sizing: border-box;
}
@media (prefers-color-scheme: light) {
.mu-15 {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
.mu-15[data-theme="light"],
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
@media (prefers-color-scheme: dark) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
@media (prefers-color-scheme: light) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
}
}
.mu-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
.mu-15__theme {
position: absolute;
inset-block-start: 1rem;
inset-inline-end: 1rem;
z-index: 5;
}
.mu-15__theme-input {
position: absolute;
inset: 0;
inline-size: 44px;
block-size: 44px;
margin: 0;
opacity: 0;
cursor: pointer;
}
.mu-15__theme-label {
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border: 1px solid var(--mu-15-edge);
border-radius: 50%;
background: var(--mu-15-surface);
color: var(--mu-15-ink-2);
cursor: pointer;
}
.mu-15__theme-label svg {
inline-size: 20px;
block-size: 20px;
}
.mu-15__theme-input:focus-visible + .mu-15__theme-label {
outline: 2px solid var(--mu-15-acc);
outline-offset: 2px;
}
.mu-15__stage {
max-inline-size: 60rem;
margin-inline: auto;
padding: 4rem 1.25rem 5rem;
display: grid;
gap: 2.5rem;
grid-template-columns: minmax(0, 1fr);
}
.mu-15__grid {
display: grid;
gap: 1.25rem;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.mu-15__card {
min-inline-size: 0;
display: grid;
gap: 0.75rem;
align-content: start;
padding: 1.5rem;
border-radius: 10px;
background: var(--mu-15-surface);
border-block-start: 1px solid var(--mu-15-edge);
}
.mu-15__card p,
.mu-15__card h3 {
margin: 0;
min-inline-size: 0;
}
.mu-15__card-head {
display: grid;
gap: 2px;
min-inline-size: 0;
}
.mu-15__label {
font-size: 0.8125rem;
font-weight: 500;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--mu-15-ink-2);
}
.mu-15__scope {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__value {
font-family: var(--mu-15-mono);
font-size: var(--mu-15-value-size);
line-height: 1.02;
letter-spacing: -0.03em;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.mu-15__delta {
display: inline-flex;
align-items: center;
gap: 0.375rem;
font-size: 0.8125rem;
font-variant-numeric: tabular-nums;
}
.mu-15__delta svg {
inline-size: 15px;
block-size: 15px;
flex: none;
}
.mu-15__delta b {
font-weight: 600;
}
.mu-15__delta span {
color: var(--mu-15-ink-2);
}
.mu-15__delta--up {
color: var(--mu-15-up);
}
.mu-15__delta--down {
color: var(--mu-15-down);
}
.mu-15__spark {
min-inline-size: 0;
aspect-ratio: 240 / 64;
color: var(--mu-15-ink-2);
margin-block-start: 0.25rem;
}
.mu-15__spark svg {
display: block;
inline-size: 100%;
block-size: 100%;
}
.mu-15__card-foot {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 0.5rem 1rem;
padding-block-start: 0.75rem;
border-block-start: 1px solid var(--mu-15-line);
}
.mu-15__foot-note {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__link {
display: inline-flex;
align-items: center;
min-block-size: 44px;
font-size: 0.8125rem;
font-weight: 600;
color: var(--mu-15-acc);
text-decoration: none;
border-block-end: 1px solid transparent;
}
.mu-15__link:hover {
border-block-end-color: currentColor;
}
.mu-15__link:focus-visible {
outline: 2px solid var(--mu-15-acc);
outline-offset: 3px;
border-radius: 2px;
}
@media (min-width: 48rem) {
.mu-15__stage {
padding-inline: 3rem;
}
.mu-15__card {
padding: 1.75rem;
}
}.mu-15 {
--mu-15-value-size: clamp(2.25rem, 1.7rem + 2.4vw, 3rem);
--mu-15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
--mu-15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
position: relative;
box-sizing: border-box;
background: var(--mu-15-bg);
color: var(--mu-15-ink);
font-family: var(--mu-15-ui);
line-height: 1.5;
-webkit-text-size-adjust: 100%;
}
.mu-15 *,
.mu-15 *::before,
.mu-15 *::after {
box-sizing: border-box;
}
@media (prefers-color-scheme: light) {
.mu-15 {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
.mu-15[data-theme="light"],
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
@media (prefers-color-scheme: dark) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
@media (prefers-color-scheme: light) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
}
}
.mu-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
.mu-15__theme {
position: absolute;
inset-block-start: 1rem;
inset-inline-end: 1rem;
z-index: 5;
}
.mu-15__theme-input {
position: absolute;
inset: 0;
inline-size: 44px;
block-size: 44px;
margin: 0;
opacity: 0;
cursor: pointer;
}
.mu-15__theme-label {
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border: 1px solid var(--mu-15-edge);
border-radius: 50%;
background: var(--mu-15-surface);
color: var(--mu-15-ink-2);
cursor: pointer;
}
.mu-15__theme-label svg {
inline-size: 20px;
block-size: 20px;
}
.mu-15__theme-input:focus-visible + .mu-15__theme-label {
outline: 2px solid var(--mu-15-acc);
outline-offset: 2px;
}
.mu-15__stage {
max-inline-size: 60rem;
margin-inline: auto;
padding: 4rem 1.25rem 5rem;
display: grid;
gap: 2.5rem;
grid-template-columns: minmax(0, 1fr);
}
.mu-15__grid {
display: grid;
gap: 1.25rem;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.mu-15__card {
min-inline-size: 0;
display: grid;
gap: 0.75rem;
align-content: start;
padding: 1.5rem;
border-radius: 10px;
background: var(--mu-15-surface);
border-block-start: 1px solid var(--mu-15-edge);
}
.mu-15__card p,
.mu-15__card h3 {
margin: 0;
min-inline-size: 0;
}
.mu-15__card-head {
display: grid;
gap: 2px;
min-inline-size: 0;
}
.mu-15__label {
font-size: 0.8125rem;
font-weight: 500;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--mu-15-ink-2);
}
.mu-15__scope {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__value {
font-family: var(--mu-15-mono);
font-size: var(--mu-15-value-size);
line-height: 1.02;
letter-spacing: -0.03em;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.mu-15__delta {
display: inline-flex;
align-items: center;
gap: 0.375rem;
font-size: 0.8125rem;
font-variant-numeric: tabular-nums;
}
.mu-15__delta svg {
inline-size: 15px;
block-size: 15px;
flex: none;
}
.mu-15__delta b {
font-weight: 600;
}
.mu-15__delta span {
color: var(--mu-15-ink-2);
}
.mu-15__delta--up {
color: var(--mu-15-up);
}
.mu-15__delta--down {
color: var(--mu-15-down);
}
.mu-15__spark {
min-inline-size: 0;
aspect-ratio: 240 / 64;
color: var(--mu-15-ink-2);
margin-block-start: 0.25rem;
}
.mu-15__spark svg {
display: block;
inline-size: 100%;
block-size: 100%;
}
.mu-15__card-foot {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 0.5rem 1rem;
padding-block-start: 0.75rem;
border-block-start: 1px solid var(--mu-15-line);
}
.mu-15__foot-note {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__link {
display: inline-flex;
align-items: center;
min-block-size: 44px;
font-size: 0.8125rem;
font-weight: 600;
color: var(--mu-15-acc);
text-decoration: none;
border-block-end: 1px solid transparent;
}
.mu-15__link:hover {
border-block-end-color: currentColor;
}
.mu-15__link:focus-visible {
outline: 2px solid var(--mu-15-acc);
outline-offset: 3px;
border-radius: 2px;
}
@media (min-width: 48rem) {
.mu-15__stage {
padding-inline: 3rem;
}
.mu-15__card {
padding: 1.75rem;
}
}Here's a working CSS Minimalist UI from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Minimalist Dashboard Card and Metric
Source: https://codefronts.com/design-styles/css-minimalist-ui/axiom-dashboard/
One metric card — value, label, delta and sparkline — where the hierarchy between the number and its label comes from scale and weight, not colour. A component study rather than a dashboard layout, so it drops into whatever grid you already have — and the delta carries a glyph and a word alongside its hue, so the direction survives for a reader who cannot resolve the colour.
## HTML
```html
<section class="mu-15" aria-labelledby="mu-15-title">
<h2 class="mu-15__sr" id="mu-15-title">Account metrics</h2>
<div class="mu-15__theme">
<input class="mu-15__theme-input" type="checkbox" id="mu-15-theme">
<label class="mu-15__theme-label" for="mu-15-theme">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="mu-15__sr">Toggle dark theme</span>
</label>
</div>
<div class="mu-15__stage">
<div class="mu-15__grid">
<article class="mu-15__card" aria-labelledby="mu-15-m1">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m1">Monthly recurring revenue</h3>
<p class="mu-15__scope">Meridian · all regions</p>
</header>
<p class="mu-15__value">$281,440</p>
<p class="mu-15__delta mu-15__delta--up">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 19V5m0 0-6 6m6-6 6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>4.2%</b> <span>vs last month</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Twelve-month trend, rising from 214,000 to 281,440">
<path d="M0 52 20 49 40 51 60 44 80 46 100 38 120 34 140 36 160 27 180 22 200 24 220 14 240 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Updated 6 min ago</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
<article class="mu-15__card" aria-labelledby="mu-15-m2">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m2">Net revenue retention</h3>
<p class="mu-15__scope">Rolling 12 months</p>
</header>
<p class="mu-15__value">104.8%</p>
<p class="mu-15__delta mu-15__delta--down">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 5v14m0 0 6-6m-6 6-6-6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>0.6pt</b> <span>vs last quarter</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Rolling retention, flat then easing from 106.1 to 104.8 percent">
<path d="M0 22 20 20 40 24 60 21 80 26 100 24 120 29 140 27 160 33 180 31 200 36 220 34 240 39" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Cohort model v4</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
</div>
</div>
</section>
```
## CSS
```css
.mu-15 {
--mu-15-value-size: clamp(2.25rem, 1.7rem + 2.4vw, 3rem);
--mu-15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
--mu-15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
position: relative;
box-sizing: border-box;
background: var(--mu-15-bg);
color: var(--mu-15-ink);
font-family: var(--mu-15-ui);
line-height: 1.5;
-webkit-text-size-adjust: 100%;
}
.mu-15 *,
.mu-15 *::before,
.mu-15 *::after {
box-sizing: border-box;
}
@media (prefers-color-scheme: light) {
.mu-15 {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
.mu-15[data-theme="light"],
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
@media (prefers-color-scheme: dark) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
@media (prefers-color-scheme: light) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
}
}
.mu-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
.mu-15__theme {
position: absolute;
inset-block-start: 1rem;
inset-inline-end: 1rem;
z-index: 5;
}
.mu-15__theme-input {
position: absolute;
inset: 0;
inline-size: 44px;
block-size: 44px;
margin: 0;
opacity: 0;
cursor: pointer;
}
.mu-15__theme-label {
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border: 1px solid var(--mu-15-edge);
border-radius: 50%;
background: var(--mu-15-surface);
color: var(--mu-15-ink-2);
cursor: pointer;
}
.mu-15__theme-label svg {
inline-size: 20px;
block-size: 20px;
}
.mu-15__theme-input:focus-visible + .mu-15__theme-label {
outline: 2px solid var(--mu-15-acc);
outline-offset: 2px;
}
.mu-15__stage {
max-inline-size: 60rem;
margin-inline: auto;
padding: 4rem 1.25rem 5rem;
display: grid;
gap: 2.5rem;
grid-template-columns: minmax(0, 1fr);
}
.mu-15__grid {
display: grid;
gap: 1.25rem;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.mu-15__card {
min-inline-size: 0;
display: grid;
gap: 0.75rem;
align-content: start;
padding: 1.5rem;
border-radius: 10px;
background: var(--mu-15-surface);
border-block-start: 1px solid var(--mu-15-edge);
}
.mu-15__card p,
.mu-15__card h3 {
margin: 0;
min-inline-size: 0;
}
.mu-15__card-head {
display: grid;
gap: 2px;
min-inline-size: 0;
}
.mu-15__label {
font-size: 0.8125rem;
font-weight: 500;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--mu-15-ink-2);
}
.mu-15__scope {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__value {
font-family: var(--mu-15-mono);
font-size: var(--mu-15-value-size);
line-height: 1.02;
letter-spacing: -0.03em;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.mu-15__delta {
display: inline-flex;
align-items: center;
gap: 0.375rem;
font-size: 0.8125rem;
font-variant-numeric: tabular-nums;
}
.mu-15__delta svg {
inline-size: 15px;
block-size: 15px;
flex: none;
}
.mu-15__delta b {
font-weight: 600;
}
.mu-15__delta span {
color: var(--mu-15-ink-2);
}
.mu-15__delta--up {
color: var(--mu-15-up);
}
.mu-15__delta--down {
color: var(--mu-15-down);
}
.mu-15__spark {
min-inline-size: 0;
aspect-ratio: 240 / 64;
color: var(--mu-15-ink-2);
margin-block-start: 0.25rem;
}
.mu-15__spark svg {
display: block;
inline-size: 100%;
block-size: 100%;
}
.mu-15__card-foot {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 0.5rem 1rem;
padding-block-start: 0.75rem;
border-block-start: 1px solid var(--mu-15-line);
}
.mu-15__foot-note {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__link {
display: inline-flex;
align-items: center;
min-block-size: 44px;
font-size: 0.8125rem;
font-weight: 600;
color: var(--mu-15-acc);
text-decoration: none;
border-block-end: 1px solid transparent;
}
.mu-15__link:hover {
border-block-end-color: currentColor;
}
.mu-15__link:focus-visible {
outline: 2px solid var(--mu-15-acc);
outline-offset: 3px;
border-radius: 2px;
}
@media (min-width: 48rem) {
.mu-15__stage {
padding-inline: 3rem;
}
.mu-15__card {
padding: 1.75rem;
}
}
```Here's a working CSS Minimalist UI from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Minimalist Dashboard Card and Metric
Source: https://codefronts.com/design-styles/css-minimalist-ui/axiom-dashboard/
One metric card — value, label, delta and sparkline — where the hierarchy between the number and its label comes from scale and weight, not colour. A component study rather than a dashboard layout, so it drops into whatever grid you already have — and the delta carries a glyph and a word alongside its hue, so the direction survives for a reader who cannot resolve the colour.
## HTML
```html
<section class="mu-15" aria-labelledby="mu-15-title">
<h2 class="mu-15__sr" id="mu-15-title">Account metrics</h2>
<div class="mu-15__theme">
<input class="mu-15__theme-input" type="checkbox" id="mu-15-theme">
<label class="mu-15__theme-label" for="mu-15-theme">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="1.6"/><path d="M12 4a8 8 0 0 0 0 16Z" fill="currentColor"/></svg>
<span class="mu-15__sr">Toggle dark theme</span>
</label>
</div>
<div class="mu-15__stage">
<div class="mu-15__grid">
<article class="mu-15__card" aria-labelledby="mu-15-m1">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m1">Monthly recurring revenue</h3>
<p class="mu-15__scope">Meridian · all regions</p>
</header>
<p class="mu-15__value">$281,440</p>
<p class="mu-15__delta mu-15__delta--up">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 19V5m0 0-6 6m6-6 6 6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>4.2%</b> <span>vs last month</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Twelve-month trend, rising from 214,000 to 281,440">
<path d="M0 52 20 49 40 51 60 44 80 46 100 38 120 34 140 36 160 27 180 22 200 24 220 14 240 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Updated 6 min ago</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
<article class="mu-15__card" aria-labelledby="mu-15-m2">
<header class="mu-15__card-head">
<h3 class="mu-15__label" id="mu-15-m2">Net revenue retention</h3>
<p class="mu-15__scope">Rolling 12 months</p>
</header>
<p class="mu-15__value">104.8%</p>
<p class="mu-15__delta mu-15__delta--down">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 5v14m0 0 6-6m-6 6-6-6" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
<b>0.6pt</b> <span>vs last quarter</span>
</p>
<div class="mu-15__spark">
<svg viewBox="0 0 240 64" preserveAspectRatio="none" role="img" aria-label="Rolling retention, flat then easing from 106.1 to 104.8 percent">
<path d="M0 22 20 20 40 24 60 21 80 26 100 24 120 29 140 27 160 33 180 31 200 36 220 34 240 39" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="mu-15__card-foot">
<p class="mu-15__foot-note">Cohort model v4</p>
<a class="mu-15__link" href="#mu-15-title">Full report</a>
</footer>
</article>
</div>
</div>
</section>
```
## CSS
```css
.mu-15 {
--mu-15-value-size: clamp(2.25rem, 1.7rem + 2.4vw, 3rem);
--mu-15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
--mu-15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
position: relative;
box-sizing: border-box;
background: var(--mu-15-bg);
color: var(--mu-15-ink);
font-family: var(--mu-15-ui);
line-height: 1.5;
-webkit-text-size-adjust: 100%;
}
.mu-15 *,
.mu-15 *::before,
.mu-15 *::after {
box-sizing: border-box;
}
@media (prefers-color-scheme: light) {
.mu-15 {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
.mu-15[data-theme="light"],
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
@media (prefers-color-scheme: dark) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #f4f5f7;
--mu-15-bg: oklch(96.5% 0.003 250);
--mu-15-surface: #ffffff;
--mu-15-surface: oklch(100% 0 0);
--mu-15-edge: #dfe3e7;
--mu-15-edge: oklch(89% 0.005 250);
--mu-15-ink: #12151a;
--mu-15-ink: oklch(19% 0.006 250);
--mu-15-ink-2: #4e575f;
--mu-15-ink-2: oklch(45% 0.012 250);
--mu-15-line: #e5e8eb;
--mu-15-line: oklch(92% 0.004 250);
--mu-15-up: #14663f;
--mu-15-up: oklch(43% 0.11 158);
--mu-15-down: #9c3f1c;
--mu-15-down: oklch(45% 0.13 40);
--mu-15-acc: #144aa8;
--mu-15-acc: oklch(42% 0.16 262);
}
}
@media (prefers-color-scheme: light) {
.mu-15:has(.mu-15__theme-input:checked) {
--mu-15-bg: #08090b;
--mu-15-bg: oklch(13% 0.004 250);
--mu-15-surface: #12151a;
--mu-15-surface: oklch(19% 0.006 250);
--mu-15-edge: #262c33;
--mu-15-edge: oklch(27% 0.008 250);
--mu-15-ink: #f3f5f7;
--mu-15-ink: oklch(96.5% 0.003 250);
--mu-15-ink-2: #a2abb3;
--mu-15-ink-2: oklch(74% 0.008 250);
--mu-15-line: #232a30;
--mu-15-line: oklch(25.5% 0.008 250);
--mu-15-up: #63d19b;
--mu-15-up: oklch(80% 0.13 158);
--mu-15-down: #f0a58a;
--mu-15-down: oklch(79% 0.11 40);
--mu-15-acc: #7fb4ff;
--mu-15-acc: oklch(79% 0.13 260);
}
}
.mu-15__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
.mu-15__theme {
position: absolute;
inset-block-start: 1rem;
inset-inline-end: 1rem;
z-index: 5;
}
.mu-15__theme-input {
position: absolute;
inset: 0;
inline-size: 44px;
block-size: 44px;
margin: 0;
opacity: 0;
cursor: pointer;
}
.mu-15__theme-label {
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border: 1px solid var(--mu-15-edge);
border-radius: 50%;
background: var(--mu-15-surface);
color: var(--mu-15-ink-2);
cursor: pointer;
}
.mu-15__theme-label svg {
inline-size: 20px;
block-size: 20px;
}
.mu-15__theme-input:focus-visible + .mu-15__theme-label {
outline: 2px solid var(--mu-15-acc);
outline-offset: 2px;
}
.mu-15__stage {
max-inline-size: 60rem;
margin-inline: auto;
padding: 4rem 1.25rem 5rem;
display: grid;
gap: 2.5rem;
grid-template-columns: minmax(0, 1fr);
}
.mu-15__grid {
display: grid;
gap: 1.25rem;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.mu-15__card {
min-inline-size: 0;
display: grid;
gap: 0.75rem;
align-content: start;
padding: 1.5rem;
border-radius: 10px;
background: var(--mu-15-surface);
border-block-start: 1px solid var(--mu-15-edge);
}
.mu-15__card p,
.mu-15__card h3 {
margin: 0;
min-inline-size: 0;
}
.mu-15__card-head {
display: grid;
gap: 2px;
min-inline-size: 0;
}
.mu-15__label {
font-size: 0.8125rem;
font-weight: 500;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--mu-15-ink-2);
}
.mu-15__scope {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__value {
font-family: var(--mu-15-mono);
font-size: var(--mu-15-value-size);
line-height: 1.02;
letter-spacing: -0.03em;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.mu-15__delta {
display: inline-flex;
align-items: center;
gap: 0.375rem;
font-size: 0.8125rem;
font-variant-numeric: tabular-nums;
}
.mu-15__delta svg {
inline-size: 15px;
block-size: 15px;
flex: none;
}
.mu-15__delta b {
font-weight: 600;
}
.mu-15__delta span {
color: var(--mu-15-ink-2);
}
.mu-15__delta--up {
color: var(--mu-15-up);
}
.mu-15__delta--down {
color: var(--mu-15-down);
}
.mu-15__spark {
min-inline-size: 0;
aspect-ratio: 240 / 64;
color: var(--mu-15-ink-2);
margin-block-start: 0.25rem;
}
.mu-15__spark svg {
display: block;
inline-size: 100%;
block-size: 100%;
}
.mu-15__card-foot {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 0.5rem 1rem;
padding-block-start: 0.75rem;
border-block-start: 1px solid var(--mu-15-line);
}
.mu-15__foot-note {
font-size: 0.75rem;
color: var(--mu-15-ink-2);
}
.mu-15__link {
display: inline-flex;
align-items: center;
min-block-size: 44px;
font-size: 0.8125rem;
font-weight: 600;
color: var(--mu-15-acc);
text-decoration: none;
border-block-end: 1px solid transparent;
}
.mu-15__link:hover {
border-block-end-color: currentColor;
}
.mu-15__link:focus-visible {
outline: 2px solid var(--mu-15-acc);
outline-offset: 3px;
border-radius: 2px;
}
@media (min-width: 48rem) {
.mu-15__stage {
padding-inline: 3rem;
}
.mu-15__card {
padding: 1.75rem;
}
}
```How this works
A metric card has exactly one job: make the number readable in a glance and the context available on the second glance. That is a hierarchy problem, and the answer is scale plus weight. The value here is 2.4× the label and 600 weight against 500; remove all colour and the order still reads instantly, which is the test from demo 02.
The delta is where these cards usually fail SC 1.4.1. Green up, red down, nothing else — and a colour-blind user gets a number with no direction. Every delta here carries an arrow glyph and the word “vs last month”, so the hue is reinforcement rather than the mechanism. The status palette is also kept separate from the accent, per demo 09.
Tabular figures are not a detail on a live dashboard. Proportional numerals change width as digits change, so a value that refreshes every thirty seconds visibly jitters and the eye keeps being pulled back to it. tabular-nums fixes the advance width and the number sits still.
Why this is a component and not a dashboard. A whole dashboard screen is a layout problem, and it teaches nothing about restraint. The interesting decisions in a metric card are all inside the card: how far apart the value and label sit, whether the sparkline needs axes (it does not), whether the border earns its place (it does not — a tonal step and a hairline do the job), and how the delta stays accessible. Ship it into your own grid.
Make it yours
- Change
--mu-15-value-sizeto retune the value against the label; keep the ratio above 2× or the hierarchy softens. - Swap the sparkline path for your own data; the
viewBoxis 0 0 240 64, so points map directly. - Set
--mu-15-edgetotransparentto test how much the hairline is carrying. - Recolour the delta with
--mu-15-upand--mu-15-down; both are separate from the accent by design. - Add a second metric by duplicating the
<article>— the grid isauto-fitand needs no changes. - Change
--mu-15-monoto a proportional stack if your product's numerals are not scanned repeatedly.
Gotchas — read before shipping
- Colouring the value itself to match the delta destroys the hierarchy: the number becomes a status indicator and stops reading as a quantity.
- A sparkline without a scale reference can imply a trend that the axis would contradict. Keep it as texture, not as evidence, and link to the real chart.
- Proportional numerals on a refreshing metric make the card visibly jitter. Use tabular figures.
- An arrow with no text label fails SC 1.4.1 for users who cannot resolve the hue and reads as decoration to a screen reader.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 121+ | 111+ |
oklch() and the :has() theme toggle set the floor. aspect-ratio (Chrome 88, Safari 15, Firefox 89) and vector-effect: non-scaling-stroke are both comfortably inside it, and the card layout is plain grid, so the component itself renders far below this floor with the sRGB hex fallbacks declared first.