15 / 20
All 20 in 20 Tailwind CSS Minimalist UI
- 01Tailwind Modular Type Scale with a Ratio Variable
- 02Tailwind Type Hierarchy Without Any Color Change
- 03Tailwind System Font Stack That Needs No Webfont
- 04Tailwind Optical Alignment vs Mathematical Centering
- 05Tailwind Spacing Scale from a Single Base Unit
- 06Tailwind Whitespace That Groups Instead of Separates
- 07Tailwind Vertical Rhythm with a Consistent Baseline
- 08Tailwind Minimal Layout with CSS Grid and No Divs
- 09Tailwind One Accent Color Restraint Budget
- 10Tailwind Grayscale Palette with Enough Contrast
- 11Tailwind Borders and Dividers You Can Actually Remove
- 12Tailwind Elevation Without Shadows or Gradients
- 13Tailwind Why Minimal Interfaces Fail Accessibility
- 14Tailwind Minimalist and Brutalist Side by Side
- 15Tailwind Minimalist Dashboard Card and Metric
- 16Tailwind Minimalist Product Card for Ecommerce
- 17Tailwind Minimalist Portfolio Project Listing
- 18Tailwind Minimalist Article Layout and Typography
- 19Tailwind Minimalist Mobile App Screen in a Frame
- 20Tailwind Minimalist Landing Page Section
Tailwind Minimalist Dashboard Card and Metric
Two KPI cards reduced to what a glance needs: label, value, direction, trend, and one way out. The value is set in tabular monospace at a fluid clamp() size, the delta is a pill carrying an arrow and a word so direction never relies on green or red, and the sparkline is a vector-effect: non-scaling-stroke SVG that keeps a crisp 1.75px line at any width.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tmu-15 relative w-full min-h-svh bg-tmu15-bg font-tmu15-ui text-tmu15-ink antialiased" aria-labelledby="tmu15-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu15-theme" type="checkbox" class="peer sr-only">
<label for="tmu15-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu15-line bg-tmu15-surface text-tmu15-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu15-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu15-acc motion-reduce:transition-none">
<svg class="size-5" 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="sr-only">Switch colour theme</span>
</label>
</div>
<div class="mx-auto grid max-w-[60rem] gap-10 px-5 pt-20 pb-20 md:px-12">
<header class="grid max-w-[62ch] gap-3">
<p class="inline-flex items-center gap-2.5 font-tmu15-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu15-ink-2"><span class="tabular-nums text-tmu15-acc">15</span><span aria-hidden="true" class="h-px w-6 bg-tmu15-line"></span>Metric card</p>
<h2 id="tmu15-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A number, a direction, a trend — nothing else</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu15-ink-2 text-pretty">Everything a glance needs and one way to go deeper. Direction is carried by an arrow and a word, never by green and red alone.</p>
</header>
<div class="grid gap-5 grid-cols-[repeat(auto-fit,minmax(min(100%,17rem),1fr))]">
<article aria-labelledby="tmu15-m1" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m1" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Monthly recurring revenue</h3><p class="text-xs text-tmu15-ink-2">Meridian · all regions</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-up-bg text-tmu15-up px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>4.2%<span class="sr-only"> vs last month</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">$281,440</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last month</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-up">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Updated 6 min ago</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
<article aria-labelledby="tmu15-m2" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m2" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Net revenue retention</h3><p class="text-xs text-tmu15-ink-2">Rolling 12 months</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-down-bg text-tmu15-down px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>0.6pt<span class="sr-only"> vs last quarter</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">104.8%</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last quarter</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-ink-2">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Cohort model v4</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
</div>
</div>
</section><section class="tmu-15 relative w-full min-h-svh bg-tmu15-bg font-tmu15-ui text-tmu15-ink antialiased" aria-labelledby="tmu15-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu15-theme" type="checkbox" class="peer sr-only">
<label for="tmu15-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu15-line bg-tmu15-surface text-tmu15-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu15-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu15-acc motion-reduce:transition-none">
<svg class="size-5" 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="sr-only">Switch colour theme</span>
</label>
</div>
<div class="mx-auto grid max-w-[60rem] gap-10 px-5 pt-20 pb-20 md:px-12">
<header class="grid max-w-[62ch] gap-3">
<p class="inline-flex items-center gap-2.5 font-tmu15-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu15-ink-2"><span class="tabular-nums text-tmu15-acc">15</span><span aria-hidden="true" class="h-px w-6 bg-tmu15-line"></span>Metric card</p>
<h2 id="tmu15-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A number, a direction, a trend — nothing else</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu15-ink-2 text-pretty">Everything a glance needs and one way to go deeper. Direction is carried by an arrow and a word, never by green and red alone.</p>
</header>
<div class="grid gap-5 grid-cols-[repeat(auto-fit,minmax(min(100%,17rem),1fr))]">
<article aria-labelledby="tmu15-m1" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m1" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Monthly recurring revenue</h3><p class="text-xs text-tmu15-ink-2">Meridian · all regions</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-up-bg text-tmu15-up px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>4.2%<span class="sr-only"> vs last month</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">$281,440</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last month</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-up">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Updated 6 min ago</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
<article aria-labelledby="tmu15-m2" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m2" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Net revenue retention</h3><p class="text-xs text-tmu15-ink-2">Rolling 12 months</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-down-bg text-tmu15-down px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>0.6pt<span class="sr-only"> vs last quarter</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">104.8%</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last quarter</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-ink-2">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Cohort model v4</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--color-tmu15-bg: light-dark(#f4f5f7, #08090b);
--color-tmu15-bg: light-dark(oklch(96.5% 0.003 250), oklch(13% 0.004 250));
--color-tmu15-surface: light-dark(#ffffff, #12151a);
--color-tmu15-surface: light-dark(oklch(100% 0 0), oklch(19% 0.006 250));
--color-tmu15-edge: light-dark(#dfe3e7, #262c33);
--color-tmu15-edge: light-dark(oklch(89% 0.005 250), oklch(27% 0.008 250));
--color-tmu15-ink: light-dark(#12151a, #f3f5f7);
--color-tmu15-ink: light-dark(oklch(19% 0.006 250), oklch(96.5% 0.003 250));
--color-tmu15-ink-2: light-dark(#4e575f, #a2abb3);
--color-tmu15-ink-2: light-dark(oklch(45% 0.012 250), oklch(74% 0.008 250));
--color-tmu15-line: light-dark(#e5e8eb, #232a30);
--color-tmu15-line: light-dark(oklch(92% 0.004 250), oklch(25.5% 0.008 250));
--color-tmu15-up: light-dark(#14663f, #63d19b);
--color-tmu15-up: light-dark(oklch(43% 0.11 158), oklch(80% 0.13 158));
--color-tmu15-down: light-dark(#9c3f1c, #f0a58a);
--color-tmu15-down: light-dark(oklch(45% 0.13 40), oklch(79% 0.11 40));
--color-tmu15-acc: light-dark(#144aa8, #7fb4ff);
--color-tmu15-acc: light-dark(oklch(42% 0.16 262), oklch(79% 0.13 260));
--color-tmu15-up-bg: color-mix(in oklab, var(--color-tmu15-up) 14%, transparent);
--color-tmu15-down-bg: color-mix(in oklab, var(--color-tmu15-down) 14%, transparent);
--color-tmu15-surface-hi: color-mix(in oklab, var(--color-tmu15-surface) 94%, var(--color-tmu15-ink));
--font-tmu15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
/* Root rule: the full-bleed contract, restated so the stage is sized before the browser build
compiles. color-scheme drives every light-dark() token above. */
.tmu-15 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
color-scheme: light dark;
}
/* Theme toggle: flip the scheme and every token follows. Mirrored for a dark OS. */
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: light;
}
}@import "tailwindcss";
@theme {
--color-tmu15-bg: light-dark(#f4f5f7, #08090b);
--color-tmu15-bg: light-dark(oklch(96.5% 0.003 250), oklch(13% 0.004 250));
--color-tmu15-surface: light-dark(#ffffff, #12151a);
--color-tmu15-surface: light-dark(oklch(100% 0 0), oklch(19% 0.006 250));
--color-tmu15-edge: light-dark(#dfe3e7, #262c33);
--color-tmu15-edge: light-dark(oklch(89% 0.005 250), oklch(27% 0.008 250));
--color-tmu15-ink: light-dark(#12151a, #f3f5f7);
--color-tmu15-ink: light-dark(oklch(19% 0.006 250), oklch(96.5% 0.003 250));
--color-tmu15-ink-2: light-dark(#4e575f, #a2abb3);
--color-tmu15-ink-2: light-dark(oklch(45% 0.012 250), oklch(74% 0.008 250));
--color-tmu15-line: light-dark(#e5e8eb, #232a30);
--color-tmu15-line: light-dark(oklch(92% 0.004 250), oklch(25.5% 0.008 250));
--color-tmu15-up: light-dark(#14663f, #63d19b);
--color-tmu15-up: light-dark(oklch(43% 0.11 158), oklch(80% 0.13 158));
--color-tmu15-down: light-dark(#9c3f1c, #f0a58a);
--color-tmu15-down: light-dark(oklch(45% 0.13 40), oklch(79% 0.11 40));
--color-tmu15-acc: light-dark(#144aa8, #7fb4ff);
--color-tmu15-acc: light-dark(oklch(42% 0.16 262), oklch(79% 0.13 260));
--color-tmu15-up-bg: color-mix(in oklab, var(--color-tmu15-up) 14%, transparent);
--color-tmu15-down-bg: color-mix(in oklab, var(--color-tmu15-down) 14%, transparent);
--color-tmu15-surface-hi: color-mix(in oklab, var(--color-tmu15-surface) 94%, var(--color-tmu15-ink));
--font-tmu15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
/* Root rule: the full-bleed contract, restated so the stage is sized before the browser build
compiles. color-scheme drives every light-dark() token above. */
.tmu-15 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
color-scheme: light dark;
}
/* Theme toggle: flip the scheme and every token follows. Mirrored for a dark OS. */
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: light;
}
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tmu15-bg: light-dark(#f4f5f7, #08090b);
--color-tmu15-bg: light-dark(oklch(96.5% 0.003 250), oklch(13% 0.004 250));
--color-tmu15-surface: light-dark(#ffffff, #12151a);
--color-tmu15-surface: light-dark(oklch(100% 0 0), oklch(19% 0.006 250));
--color-tmu15-edge: light-dark(#dfe3e7, #262c33);
--color-tmu15-edge: light-dark(oklch(89% 0.005 250), oklch(27% 0.008 250));
--color-tmu15-ink: light-dark(#12151a, #f3f5f7);
--color-tmu15-ink: light-dark(oklch(19% 0.006 250), oklch(96.5% 0.003 250));
--color-tmu15-ink-2: light-dark(#4e575f, #a2abb3);
--color-tmu15-ink-2: light-dark(oklch(45% 0.012 250), oklch(74% 0.008 250));
--color-tmu15-line: light-dark(#e5e8eb, #232a30);
--color-tmu15-line: light-dark(oklch(92% 0.004 250), oklch(25.5% 0.008 250));
--color-tmu15-up: light-dark(#14663f, #63d19b);
--color-tmu15-up: light-dark(oklch(43% 0.11 158), oklch(80% 0.13 158));
--color-tmu15-down: light-dark(#9c3f1c, #f0a58a);
--color-tmu15-down: light-dark(oklch(45% 0.13 40), oklch(79% 0.11 40));
--color-tmu15-acc: light-dark(#144aa8, #7fb4ff);
--color-tmu15-acc: light-dark(oklch(42% 0.16 262), oklch(79% 0.13 260));
--color-tmu15-up-bg: color-mix(in oklab, var(--color-tmu15-up) 14%, transparent);
--color-tmu15-down-bg: color-mix(in oklab, var(--color-tmu15-down) 14%, transparent);
--color-tmu15-surface-hi: color-mix(in oklab, var(--color-tmu15-surface) 94%, var(--color-tmu15-ink));
--font-tmu15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
/* Root rule: the full-bleed contract, restated so the stage is sized before the browser build
compiles. color-scheme drives every light-dark() token above. */
.tmu-15 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
color-scheme: light dark;
}
/* Theme toggle: flip the scheme and every token follows. Mirrored for a dark OS. */
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: light;
}
}@import "tailwindcss";
@theme {
--color-tmu15-bg: light-dark(#f4f5f7, #08090b);
--color-tmu15-bg: light-dark(oklch(96.5% 0.003 250), oklch(13% 0.004 250));
--color-tmu15-surface: light-dark(#ffffff, #12151a);
--color-tmu15-surface: light-dark(oklch(100% 0 0), oklch(19% 0.006 250));
--color-tmu15-edge: light-dark(#dfe3e7, #262c33);
--color-tmu15-edge: light-dark(oklch(89% 0.005 250), oklch(27% 0.008 250));
--color-tmu15-ink: light-dark(#12151a, #f3f5f7);
--color-tmu15-ink: light-dark(oklch(19% 0.006 250), oklch(96.5% 0.003 250));
--color-tmu15-ink-2: light-dark(#4e575f, #a2abb3);
--color-tmu15-ink-2: light-dark(oklch(45% 0.012 250), oklch(74% 0.008 250));
--color-tmu15-line: light-dark(#e5e8eb, #232a30);
--color-tmu15-line: light-dark(oklch(92% 0.004 250), oklch(25.5% 0.008 250));
--color-tmu15-up: light-dark(#14663f, #63d19b);
--color-tmu15-up: light-dark(oklch(43% 0.11 158), oklch(80% 0.13 158));
--color-tmu15-down: light-dark(#9c3f1c, #f0a58a);
--color-tmu15-down: light-dark(oklch(45% 0.13 40), oklch(79% 0.11 40));
--color-tmu15-acc: light-dark(#144aa8, #7fb4ff);
--color-tmu15-acc: light-dark(oklch(42% 0.16 262), oklch(79% 0.13 260));
--color-tmu15-up-bg: color-mix(in oklab, var(--color-tmu15-up) 14%, transparent);
--color-tmu15-down-bg: color-mix(in oklab, var(--color-tmu15-down) 14%, transparent);
--color-tmu15-surface-hi: color-mix(in oklab, var(--color-tmu15-surface) 94%, var(--color-tmu15-ink));
--font-tmu15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
/* Root rule: the full-bleed contract, restated so the stage is sized before the browser build
compiles. color-scheme drives every light-dark() token above. */
.tmu-15 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
color-scheme: light dark;
}
/* Theme toggle: flip the scheme and every token follows. Mirrored for a dark OS. */
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: light;
}
}What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The
--value-sizecustom property became the bracketclamp()directly on the value — it had one consumer, so a token added indirection without reuse. - UI upgrade: the delta moved into the card header as a pill, the value gets the full row, and the comparison period is spelled out underneath — the number now reads first, as a KPI should.
- UI upgrade: a faint area fill under the rising trend, a subtle hover surface on the whole card, and an arrow on the report link.
Here's a working CSS demo 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: Tailwind Minimalist Dashboard Card and Metric
Source: https://codefronts.com/design-styles/tailwind-css-minimalist-ui/tailwind-minimalist-dashboard-metric-card/
Two KPI cards reduced to what a glance needs: label, value, direction, trend, and one way out. The value is set in tabular monospace at a fluid clamp() size, the delta is a pill carrying an arrow and a word so direction never relies on green or red, and the sparkline is a vector-effect: non-scaling-stroke SVG that keeps a crisp 1.75px line at any width.
## HTML
```html
<section class="tmu-15 relative w-full min-h-svh bg-tmu15-bg font-tmu15-ui text-tmu15-ink antialiased" aria-labelledby="tmu15-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu15-theme" type="checkbox" class="peer sr-only">
<label for="tmu15-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu15-line bg-tmu15-surface text-tmu15-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu15-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu15-acc motion-reduce:transition-none">
<svg class="size-5" 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="sr-only">Switch colour theme</span>
</label>
</div>
<div class="mx-auto grid max-w-[60rem] gap-10 px-5 pt-20 pb-20 md:px-12">
<header class="grid max-w-[62ch] gap-3">
<p class="inline-flex items-center gap-2.5 font-tmu15-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu15-ink-2"><span class="tabular-nums text-tmu15-acc">15</span><span aria-hidden="true" class="h-px w-6 bg-tmu15-line"></span>Metric card</p>
<h2 id="tmu15-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A number, a direction, a trend — nothing else</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu15-ink-2 text-pretty">Everything a glance needs and one way to go deeper. Direction is carried by an arrow and a word, never by green and red alone.</p>
</header>
<div class="grid gap-5 grid-cols-[repeat(auto-fit,minmax(min(100%,17rem),1fr))]">
<article aria-labelledby="tmu15-m1" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m1" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Monthly recurring revenue</h3><p class="text-xs text-tmu15-ink-2">Meridian · all regions</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-up-bg text-tmu15-up px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>4.2%<span class="sr-only"> vs last month</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">$281,440</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last month</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-up">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Updated 6 min ago</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
<article aria-labelledby="tmu15-m2" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m2" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Net revenue retention</h3><p class="text-xs text-tmu15-ink-2">Rolling 12 months</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-down-bg text-tmu15-down px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>0.6pt<span class="sr-only"> vs last quarter</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">104.8%</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last quarter</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-ink-2">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Cohort model v4</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tmu15-bg: light-dark(#f4f5f7, #08090b);
--color-tmu15-bg: light-dark(oklch(96.5% 0.003 250), oklch(13% 0.004 250));
--color-tmu15-surface: light-dark(#ffffff, #12151a);
--color-tmu15-surface: light-dark(oklch(100% 0 0), oklch(19% 0.006 250));
--color-tmu15-edge: light-dark(#dfe3e7, #262c33);
--color-tmu15-edge: light-dark(oklch(89% 0.005 250), oklch(27% 0.008 250));
--color-tmu15-ink: light-dark(#12151a, #f3f5f7);
--color-tmu15-ink: light-dark(oklch(19% 0.006 250), oklch(96.5% 0.003 250));
--color-tmu15-ink-2: light-dark(#4e575f, #a2abb3);
--color-tmu15-ink-2: light-dark(oklch(45% 0.012 250), oklch(74% 0.008 250));
--color-tmu15-line: light-dark(#e5e8eb, #232a30);
--color-tmu15-line: light-dark(oklch(92% 0.004 250), oklch(25.5% 0.008 250));
--color-tmu15-up: light-dark(#14663f, #63d19b);
--color-tmu15-up: light-dark(oklch(43% 0.11 158), oklch(80% 0.13 158));
--color-tmu15-down: light-dark(#9c3f1c, #f0a58a);
--color-tmu15-down: light-dark(oklch(45% 0.13 40), oklch(79% 0.11 40));
--color-tmu15-acc: light-dark(#144aa8, #7fb4ff);
--color-tmu15-acc: light-dark(oklch(42% 0.16 262), oklch(79% 0.13 260));
--color-tmu15-up-bg: color-mix(in oklab, var(--color-tmu15-up) 14%, transparent);
--color-tmu15-down-bg: color-mix(in oklab, var(--color-tmu15-down) 14%, transparent);
--color-tmu15-surface-hi: color-mix(in oklab, var(--color-tmu15-surface) 94%, var(--color-tmu15-ink));
--font-tmu15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
/* Root rule: the full-bleed contract, restated so the stage is sized before the browser build
compiles. color-scheme drives every light-dark() token above. */
.tmu-15 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
color-scheme: light dark;
}
/* Theme toggle: flip the scheme and every token follows. Mirrored for a dark OS. */
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: light;
}
}
```Here's a working CSS demo 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: Tailwind Minimalist Dashboard Card and Metric
Source: https://codefronts.com/design-styles/tailwind-css-minimalist-ui/tailwind-minimalist-dashboard-metric-card/
Two KPI cards reduced to what a glance needs: label, value, direction, trend, and one way out. The value is set in tabular monospace at a fluid clamp() size, the delta is a pill carrying an arrow and a word so direction never relies on green or red, and the sparkline is a vector-effect: non-scaling-stroke SVG that keeps a crisp 1.75px line at any width.
## HTML
```html
<section class="tmu-15 relative w-full min-h-svh bg-tmu15-bg font-tmu15-ui text-tmu15-ink antialiased" aria-labelledby="tmu15-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu15-theme" type="checkbox" class="peer sr-only">
<label for="tmu15-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu15-line bg-tmu15-surface text-tmu15-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu15-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu15-acc motion-reduce:transition-none">
<svg class="size-5" 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="sr-only">Switch colour theme</span>
</label>
</div>
<div class="mx-auto grid max-w-[60rem] gap-10 px-5 pt-20 pb-20 md:px-12">
<header class="grid max-w-[62ch] gap-3">
<p class="inline-flex items-center gap-2.5 font-tmu15-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu15-ink-2"><span class="tabular-nums text-tmu15-acc">15</span><span aria-hidden="true" class="h-px w-6 bg-tmu15-line"></span>Metric card</p>
<h2 id="tmu15-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A number, a direction, a trend — nothing else</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu15-ink-2 text-pretty">Everything a glance needs and one way to go deeper. Direction is carried by an arrow and a word, never by green and red alone.</p>
</header>
<div class="grid gap-5 grid-cols-[repeat(auto-fit,minmax(min(100%,17rem),1fr))]">
<article aria-labelledby="tmu15-m1" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m1" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Monthly recurring revenue</h3><p class="text-xs text-tmu15-ink-2">Meridian · all regions</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-up-bg text-tmu15-up px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>4.2%<span class="sr-only"> vs last month</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">$281,440</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last month</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-up">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Updated 6 min ago</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
<article aria-labelledby="tmu15-m2" class="group grid min-w-0 content-start gap-3 rounded-2xl border-t border-tmu15-edge bg-tmu15-surface p-6 transition-colors duration-200 hover:bg-tmu15-surface-hi md:p-7 motion-reduce:transition-none">
<header class="flex min-w-0 items-start justify-between gap-3">
<div class="grid min-w-0 gap-0.5"><h3 id="tmu15-m2" class="text-[0.8125rem] font-medium uppercase tracking-[0.06em] text-tmu15-ink-2">Net revenue retention</h3><p class="text-xs text-tmu15-ink-2">Rolling 12 months</p></div>
<p class="inline-flex flex-none items-center gap-1 rounded-full bg-tmu15-down-bg text-tmu15-down px-2 py-1 text-xs font-semibold tabular-nums"><svg class="size-3.5 flex-none" 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.4" stroke-linecap="round"/></svg>0.6pt<span class="sr-only"> vs last quarter</span></p>
</header>
<p class="font-tmu15-mono text-[clamp(2.25rem,1.7rem+2.4vw,3rem)] font-semibold leading-[1.02] tracking-[-0.03em] tabular-nums">104.8%</p>
<p class="text-[0.8125rem] text-tmu15-ink-2">vs last quarter</p>
<div class="mt-1 aspect-[240/64] min-w-0 text-tmu15-ink-2">
<svg class="block size-full overflow-visible" 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 240 64 0 64Z" fill="currentColor" opacity="0.08"/>
<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.75" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<footer class="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t border-tmu15-line pt-3">
<p class="text-xs text-tmu15-ink-2">Cohort model v4</p>
<a href="#tmu15-title" class="inline-flex min-h-11 items-center gap-1 text-[0.8125rem] font-semibold text-tmu15-acc underline decoration-transparent underline-offset-4 transition-[text-decoration-color] duration-150 hover:decoration-current focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tmu15-acc motion-reduce:transition-none">Full report<svg class="size-3.5 transition-transform duration-150 group-hover:translate-x-0.5 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 12h13m0 0-5-5m5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></a>
</footer>
</article>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tmu15-bg: light-dark(#f4f5f7, #08090b);
--color-tmu15-bg: light-dark(oklch(96.5% 0.003 250), oklch(13% 0.004 250));
--color-tmu15-surface: light-dark(#ffffff, #12151a);
--color-tmu15-surface: light-dark(oklch(100% 0 0), oklch(19% 0.006 250));
--color-tmu15-edge: light-dark(#dfe3e7, #262c33);
--color-tmu15-edge: light-dark(oklch(89% 0.005 250), oklch(27% 0.008 250));
--color-tmu15-ink: light-dark(#12151a, #f3f5f7);
--color-tmu15-ink: light-dark(oklch(19% 0.006 250), oklch(96.5% 0.003 250));
--color-tmu15-ink-2: light-dark(#4e575f, #a2abb3);
--color-tmu15-ink-2: light-dark(oklch(45% 0.012 250), oklch(74% 0.008 250));
--color-tmu15-line: light-dark(#e5e8eb, #232a30);
--color-tmu15-line: light-dark(oklch(92% 0.004 250), oklch(25.5% 0.008 250));
--color-tmu15-up: light-dark(#14663f, #63d19b);
--color-tmu15-up: light-dark(oklch(43% 0.11 158), oklch(80% 0.13 158));
--color-tmu15-down: light-dark(#9c3f1c, #f0a58a);
--color-tmu15-down: light-dark(oklch(45% 0.13 40), oklch(79% 0.11 40));
--color-tmu15-acc: light-dark(#144aa8, #7fb4ff);
--color-tmu15-acc: light-dark(oklch(42% 0.16 262), oklch(79% 0.13 260));
--color-tmu15-up-bg: color-mix(in oklab, var(--color-tmu15-up) 14%, transparent);
--color-tmu15-down-bg: color-mix(in oklab, var(--color-tmu15-down) 14%, transparent);
--color-tmu15-surface-hi: color-mix(in oklab, var(--color-tmu15-surface) 94%, var(--color-tmu15-ink));
--font-tmu15-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu15-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
/* Root rule: the full-bleed contract, restated so the stage is sized before the browser build
compiles. color-scheme drives every light-dark() token above. */
.tmu-15 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
color-scheme: light dark;
}
/* Theme toggle: flip the scheme and every token follows. Mirrored for a dark OS. */
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-15:has(#tmu15-theme:checked) {
color-scheme: light;
}
}
```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
- Swap the area fill off by deleting the first
<path>in each sparkline. - Add a third card — the grid is
repeat(auto-fit,minmax(min(100%,17rem),1fr))and reflows on its own. - Retheme up/down through
--color-tmu15-up/--color-tmu15-down; their pill grounds are mixes of them.
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 |
|---|---|---|---|
| 123+ | 17.5+ | 128+ | 123+ |
The floor is set by light-dark() on the colour tokens (Chrome 123 / Safari 17.5 / Firefox 120) and by Tailwind v4's own generated sheet (cascade layers, @property, color-mix()). The technique itself works far further back.