10 / 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 Grayscale Palette with Enough Contrast
A ten-step neutral ramp with its measured contrast ratio printed against the active surface, and a verdict per step. Flip the theme and every ratio, verdict and the 4.5:1 floor marker swaps — driven by a custom tmu10-dark: variant that knows about both the OS preference and the toggle, so the table is honest in all four combinations.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tmu-10 relative w-full min-h-svh bg-tmu10-bg font-tmu10-ui text-tmu10-ink antialiased" aria-labelledby="tmu10-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu10-theme" type="checkbox" class="peer sr-only">
<label for="tmu10-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu10-line bg-tmu10-bg text-tmu10-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu10-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu10-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-[64rem] 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-tmu10-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu10-ink-2"><span class="tabular-nums text-tmu10-acc">10</span><span aria-hidden="true" class="h-px w-6 bg-tmu10-line"></span>Contrast</p>
<h2 id="tmu10-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A grey is only minimal if it can be read</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu10-ink-2 text-pretty">Every step of the ramp, measured against the surface you are looking at right now. Switch the theme — the ratios, verdicts and the floor move with it.</p>
</header>
<div role="table" aria-labelledby="tmu10-cap" class="grid min-w-0 border-t border-tmu10-line">
<p id="tmu10-cap" class="py-3 font-tmu10-mono text-xs text-tmu10-ink-2"><span class="tmu10-dark:hidden">Ratios against the light surface #ffffff</span><span class="hidden tmu10-dark:inline">Ratios against the dark surface #14171a</span></p>
<div role="row" class="grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-2.5 font-tmu10-mono text-[0.6875rem] uppercase tracking-[0.1em] text-tmu10-ink-2">
<span role="columnheader">Step</span><span role="columnheader">Swatch</span><span role="columnheader">Sample</span><span role="columnheader" class="text-right">Ratio</span><span role="columnheader" class="col-[3/-1] sm:col-auto sm:justify-self-end">Verdict</span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">050</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t050"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t050">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.07:1</b><b class="hidden font-medium tmu10-dark:inline">16.28:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">100</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t100"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t100">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.22:1</b><b class="hidden font-medium tmu10-dark:inline">13.49:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">200</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t200"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t200">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.51:1</b><b class="hidden font-medium tmu10-dark:inline">10.36:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Decorative rule</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">300</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t300"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t300">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.12:1</b><b class="hidden font-medium tmu10-dark:inline">7.20:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none tmu10-dark:border-t-2 tmu10-dark:border-t-tmu10-ink">
<span class="absolute -top-2.5 right-0 hidden rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:inline">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">400</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t400"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t400">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.96:1</b><b class="hidden font-medium tmu10-dark:inline">4.98:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">500</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t500"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t500">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">4.07:1</b><b class="hidden font-medium tmu10-dark:inline">3.55:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none border-t-2 border-t-tmu10-ink tmu10-dark:border-t-0">
<span class="absolute -top-2.5 right-0 rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:hidden">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">600</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t600"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t600">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">5.85:1</b><b class="hidden font-medium tmu10-dark:inline">2.75:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">700</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t700"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t700">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">8.60:1</b><b class="hidden font-medium tmu10-dark:inline">1.95:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">800</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t800"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t800">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">12.99:1</b><b class="hidden font-medium tmu10-dark:inline">1.42:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">900</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t900"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t900">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">17.65:1</b><b class="hidden font-medium tmu10-dark:inline">1.18:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
</div>
</div>
</section><section class="tmu-10 relative w-full min-h-svh bg-tmu10-bg font-tmu10-ui text-tmu10-ink antialiased" aria-labelledby="tmu10-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu10-theme" type="checkbox" class="peer sr-only">
<label for="tmu10-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu10-line bg-tmu10-bg text-tmu10-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu10-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu10-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-[64rem] 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-tmu10-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu10-ink-2"><span class="tabular-nums text-tmu10-acc">10</span><span aria-hidden="true" class="h-px w-6 bg-tmu10-line"></span>Contrast</p>
<h2 id="tmu10-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A grey is only minimal if it can be read</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu10-ink-2 text-pretty">Every step of the ramp, measured against the surface you are looking at right now. Switch the theme — the ratios, verdicts and the floor move with it.</p>
</header>
<div role="table" aria-labelledby="tmu10-cap" class="grid min-w-0 border-t border-tmu10-line">
<p id="tmu10-cap" class="py-3 font-tmu10-mono text-xs text-tmu10-ink-2"><span class="tmu10-dark:hidden">Ratios against the light surface #ffffff</span><span class="hidden tmu10-dark:inline">Ratios against the dark surface #14171a</span></p>
<div role="row" class="grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-2.5 font-tmu10-mono text-[0.6875rem] uppercase tracking-[0.1em] text-tmu10-ink-2">
<span role="columnheader">Step</span><span role="columnheader">Swatch</span><span role="columnheader">Sample</span><span role="columnheader" class="text-right">Ratio</span><span role="columnheader" class="col-[3/-1] sm:col-auto sm:justify-self-end">Verdict</span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">050</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t050"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t050">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.07:1</b><b class="hidden font-medium tmu10-dark:inline">16.28:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">100</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t100"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t100">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.22:1</b><b class="hidden font-medium tmu10-dark:inline">13.49:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">200</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t200"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t200">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.51:1</b><b class="hidden font-medium tmu10-dark:inline">10.36:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Decorative rule</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">300</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t300"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t300">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.12:1</b><b class="hidden font-medium tmu10-dark:inline">7.20:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none tmu10-dark:border-t-2 tmu10-dark:border-t-tmu10-ink">
<span class="absolute -top-2.5 right-0 hidden rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:inline">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">400</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t400"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t400">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.96:1</b><b class="hidden font-medium tmu10-dark:inline">4.98:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">500</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t500"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t500">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">4.07:1</b><b class="hidden font-medium tmu10-dark:inline">3.55:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none border-t-2 border-t-tmu10-ink tmu10-dark:border-t-0">
<span class="absolute -top-2.5 right-0 rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:hidden">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">600</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t600"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t600">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">5.85:1</b><b class="hidden font-medium tmu10-dark:inline">2.75:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">700</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t700"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t700">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">8.60:1</b><b class="hidden font-medium tmu10-dark:inline">1.95:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">800</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t800"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t800">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">12.99:1</b><b class="hidden font-medium tmu10-dark:inline">1.42:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">900</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t900"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t900">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">17.65:1</b><b class="hidden font-medium tmu10-dark:inline">1.18:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--color-tmu10-ground: light-dark(#ffffff, #14171a);
--color-tmu10-ground: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-bg: light-dark(#ffffff, #14171a);
--color-tmu10-bg: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-ink: light-dark(#16191c, #e9ecee);
--color-tmu10-ink: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-ink-2: light-dark(#5d666e, #a1a9b0);
--color-tmu10-ink-2: light-dark(oklch(48% 0.012 250), oklch(73% 0.008 250));
--color-tmu10-line: light-dark(#cfd3d7, #343b41);
--color-tmu10-line: light-dark(oklch(85.5% 0.005 250), oklch(33.5% 0.009 250));
--color-tmu10-ok: light-dark(#16663d, #62c78f);
--color-tmu10-ok: light-dark(oklch(44% 0.11 155), oklch(78% 0.12 155));
--color-tmu10-bad: light-dark(#a32020, #f08a8a);
--color-tmu10-bad: light-dark(oklch(45% 0.18 25), oklch(74% 0.14 25));
--color-tmu10-acc: light-dark(#16191c, #e9ecee);
--color-tmu10-acc: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-t050: light-dark(#f6f7f8, #eef1f3);
--color-tmu10-t100: light-dark(#e7e9eb, #d8dde0);
--color-tmu10-t200: light-dark(#cfd3d7, #bcc3c8);
--color-tmu10-t300: light-dark(#adb3b9, #9aa3aa);
--color-tmu10-t400: light-dark(#8f979e, #7d868d);
--color-tmu10-t500: light-dark(#767f87, #656e75);
--color-tmu10-t600: light-dark(#5d666e, #545d64);
--color-tmu10-t700: light-dark(#454d54, #3f474d);
--color-tmu10-t800: light-dark(#2b3238, #2b3238);
--color-tmu10-t900: light-dark(#16191c, #1e2429);
--color-tmu10-ok-bg: color-mix(in oklab, var(--color-tmu10-ok) 12%, transparent);
--color-tmu10-bad-bg: color-mix(in oklab, var(--color-tmu10-bad) 12%, transparent);
--font-tmu10-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu10-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-10 {
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-10:has(#tmu10-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-10:has(#tmu10-theme:checked) {
color-scheme: light;
}
}
/* "Effective dark": dark OS without the toggle, or light OS with it. One variant for both. */
@custom-variant tmu10-dark {
@media (prefers-color-scheme: dark) {
.tmu-10:not(:has(#tmu10-theme:checked)) & {
@slot;
}
}
@media (prefers-color-scheme: light) {
.tmu-10:has(#tmu10-theme:checked) & {
@slot;
}
}
}@import "tailwindcss";
@theme {
--color-tmu10-ground: light-dark(#ffffff, #14171a);
--color-tmu10-ground: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-bg: light-dark(#ffffff, #14171a);
--color-tmu10-bg: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-ink: light-dark(#16191c, #e9ecee);
--color-tmu10-ink: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-ink-2: light-dark(#5d666e, #a1a9b0);
--color-tmu10-ink-2: light-dark(oklch(48% 0.012 250), oklch(73% 0.008 250));
--color-tmu10-line: light-dark(#cfd3d7, #343b41);
--color-tmu10-line: light-dark(oklch(85.5% 0.005 250), oklch(33.5% 0.009 250));
--color-tmu10-ok: light-dark(#16663d, #62c78f);
--color-tmu10-ok: light-dark(oklch(44% 0.11 155), oklch(78% 0.12 155));
--color-tmu10-bad: light-dark(#a32020, #f08a8a);
--color-tmu10-bad: light-dark(oklch(45% 0.18 25), oklch(74% 0.14 25));
--color-tmu10-acc: light-dark(#16191c, #e9ecee);
--color-tmu10-acc: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-t050: light-dark(#f6f7f8, #eef1f3);
--color-tmu10-t100: light-dark(#e7e9eb, #d8dde0);
--color-tmu10-t200: light-dark(#cfd3d7, #bcc3c8);
--color-tmu10-t300: light-dark(#adb3b9, #9aa3aa);
--color-tmu10-t400: light-dark(#8f979e, #7d868d);
--color-tmu10-t500: light-dark(#767f87, #656e75);
--color-tmu10-t600: light-dark(#5d666e, #545d64);
--color-tmu10-t700: light-dark(#454d54, #3f474d);
--color-tmu10-t800: light-dark(#2b3238, #2b3238);
--color-tmu10-t900: light-dark(#16191c, #1e2429);
--color-tmu10-ok-bg: color-mix(in oklab, var(--color-tmu10-ok) 12%, transparent);
--color-tmu10-bad-bg: color-mix(in oklab, var(--color-tmu10-bad) 12%, transparent);
--font-tmu10-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu10-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-10 {
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-10:has(#tmu10-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-10:has(#tmu10-theme:checked) {
color-scheme: light;
}
}
/* "Effective dark": dark OS without the toggle, or light OS with it. One variant for both. */
@custom-variant tmu10-dark {
@media (prefers-color-scheme: dark) {
.tmu-10:not(:has(#tmu10-theme:checked)) & {
@slot;
}
}
@media (prefers-color-scheme: light) {
.tmu-10:has(#tmu10-theme:checked) & {
@slot;
}
}
}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-tmu10-ground: light-dark(#ffffff, #14171a);
--color-tmu10-ground: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-bg: light-dark(#ffffff, #14171a);
--color-tmu10-bg: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-ink: light-dark(#16191c, #e9ecee);
--color-tmu10-ink: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-ink-2: light-dark(#5d666e, #a1a9b0);
--color-tmu10-ink-2: light-dark(oklch(48% 0.012 250), oklch(73% 0.008 250));
--color-tmu10-line: light-dark(#cfd3d7, #343b41);
--color-tmu10-line: light-dark(oklch(85.5% 0.005 250), oklch(33.5% 0.009 250));
--color-tmu10-ok: light-dark(#16663d, #62c78f);
--color-tmu10-ok: light-dark(oklch(44% 0.11 155), oklch(78% 0.12 155));
--color-tmu10-bad: light-dark(#a32020, #f08a8a);
--color-tmu10-bad: light-dark(oklch(45% 0.18 25), oklch(74% 0.14 25));
--color-tmu10-acc: light-dark(#16191c, #e9ecee);
--color-tmu10-acc: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-t050: light-dark(#f6f7f8, #eef1f3);
--color-tmu10-t100: light-dark(#e7e9eb, #d8dde0);
--color-tmu10-t200: light-dark(#cfd3d7, #bcc3c8);
--color-tmu10-t300: light-dark(#adb3b9, #9aa3aa);
--color-tmu10-t400: light-dark(#8f979e, #7d868d);
--color-tmu10-t500: light-dark(#767f87, #656e75);
--color-tmu10-t600: light-dark(#5d666e, #545d64);
--color-tmu10-t700: light-dark(#454d54, #3f474d);
--color-tmu10-t800: light-dark(#2b3238, #2b3238);
--color-tmu10-t900: light-dark(#16191c, #1e2429);
--color-tmu10-ok-bg: color-mix(in oklab, var(--color-tmu10-ok) 12%, transparent);
--color-tmu10-bad-bg: color-mix(in oklab, var(--color-tmu10-bad) 12%, transparent);
--font-tmu10-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu10-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-10 {
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-10:has(#tmu10-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-10:has(#tmu10-theme:checked) {
color-scheme: light;
}
}
/* "Effective dark": dark OS without the toggle, or light OS with it. One variant for both. */
@custom-variant tmu10-dark {
@media (prefers-color-scheme: dark) {
.tmu-10:not(:has(#tmu10-theme:checked)) & {
@slot;
}
}
@media (prefers-color-scheme: light) {
.tmu-10:has(#tmu10-theme:checked) & {
@slot;
}
}
}@import "tailwindcss";
@theme {
--color-tmu10-ground: light-dark(#ffffff, #14171a);
--color-tmu10-ground: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-bg: light-dark(#ffffff, #14171a);
--color-tmu10-bg: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-ink: light-dark(#16191c, #e9ecee);
--color-tmu10-ink: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-ink-2: light-dark(#5d666e, #a1a9b0);
--color-tmu10-ink-2: light-dark(oklch(48% 0.012 250), oklch(73% 0.008 250));
--color-tmu10-line: light-dark(#cfd3d7, #343b41);
--color-tmu10-line: light-dark(oklch(85.5% 0.005 250), oklch(33.5% 0.009 250));
--color-tmu10-ok: light-dark(#16663d, #62c78f);
--color-tmu10-ok: light-dark(oklch(44% 0.11 155), oklch(78% 0.12 155));
--color-tmu10-bad: light-dark(#a32020, #f08a8a);
--color-tmu10-bad: light-dark(oklch(45% 0.18 25), oklch(74% 0.14 25));
--color-tmu10-acc: light-dark(#16191c, #e9ecee);
--color-tmu10-acc: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-t050: light-dark(#f6f7f8, #eef1f3);
--color-tmu10-t100: light-dark(#e7e9eb, #d8dde0);
--color-tmu10-t200: light-dark(#cfd3d7, #bcc3c8);
--color-tmu10-t300: light-dark(#adb3b9, #9aa3aa);
--color-tmu10-t400: light-dark(#8f979e, #7d868d);
--color-tmu10-t500: light-dark(#767f87, #656e75);
--color-tmu10-t600: light-dark(#5d666e, #545d64);
--color-tmu10-t700: light-dark(#454d54, #3f474d);
--color-tmu10-t800: light-dark(#2b3238, #2b3238);
--color-tmu10-t900: light-dark(#16191c, #1e2429);
--color-tmu10-ok-bg: color-mix(in oklab, var(--color-tmu10-ok) 12%, transparent);
--color-tmu10-bad-bg: color-mix(in oklab, var(--color-tmu10-bad) 12%, transparent);
--font-tmu10-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu10-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-10 {
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-10:has(#tmu10-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-10:has(#tmu10-theme:checked) {
color-scheme: light;
}
}
/* "Effective dark": dark OS without the toggle, or light OS with it. One variant for both. */
@custom-variant tmu10-dark {
@media (prefers-color-scheme: dark) {
.tmu-10:not(:has(#tmu10-theme:checked)) & {
@slot;
}
}
@media (prefers-color-scheme: light) {
.tmu-10:has(#tmu10-theme:checked) & {
@slot;
}
}
}What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The CSS original toggled read-outs with
display: var(--d-l)tokens flipped per scheme — a trick that cannot be a utility.@custom-variantreplaces it with a readable class on each element, and the floor-marker border becametmu10-dark:border-t-2instead of aborder: var(--cut-d)token. - A plain
dark:variant would not do: v4's defaultdark:follows only the OS, so the toggle would re-tone the ramp without swapping the ratios. The custom variant fixes the combination. - UI upgrade: the 4.5:1 cut line now carries a labelled 4.5:1 floor tag, verdicts became tinted pills, and a caption states which surface the ratios are measured against — it swaps with the theme too.
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 Grayscale Palette with Enough Contrast
Source: https://codefronts.com/design-styles/tailwind-css-minimalist-ui/tailwind-grayscale-palette-contrast-ratio/
A ten-step neutral ramp with its measured contrast ratio printed against the active surface, and a verdict per step. Flip the theme and every ratio, verdict and the 4.5:1 floor marker swaps — driven by a custom tmu10-dark: variant that knows about both the OS preference and the toggle, so the table is honest in all four combinations.
## HTML
```html
<section class="tmu-10 relative w-full min-h-svh bg-tmu10-bg font-tmu10-ui text-tmu10-ink antialiased" aria-labelledby="tmu10-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu10-theme" type="checkbox" class="peer sr-only">
<label for="tmu10-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu10-line bg-tmu10-bg text-tmu10-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu10-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu10-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-[64rem] 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-tmu10-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu10-ink-2"><span class="tabular-nums text-tmu10-acc">10</span><span aria-hidden="true" class="h-px w-6 bg-tmu10-line"></span>Contrast</p>
<h2 id="tmu10-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A grey is only minimal if it can be read</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu10-ink-2 text-pretty">Every step of the ramp, measured against the surface you are looking at right now. Switch the theme — the ratios, verdicts and the floor move with it.</p>
</header>
<div role="table" aria-labelledby="tmu10-cap" class="grid min-w-0 border-t border-tmu10-line">
<p id="tmu10-cap" class="py-3 font-tmu10-mono text-xs text-tmu10-ink-2"><span class="tmu10-dark:hidden">Ratios against the light surface #ffffff</span><span class="hidden tmu10-dark:inline">Ratios against the dark surface #14171a</span></p>
<div role="row" class="grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-2.5 font-tmu10-mono text-[0.6875rem] uppercase tracking-[0.1em] text-tmu10-ink-2">
<span role="columnheader">Step</span><span role="columnheader">Swatch</span><span role="columnheader">Sample</span><span role="columnheader" class="text-right">Ratio</span><span role="columnheader" class="col-[3/-1] sm:col-auto sm:justify-self-end">Verdict</span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">050</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t050"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t050">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.07:1</b><b class="hidden font-medium tmu10-dark:inline">16.28:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">100</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t100"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t100">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.22:1</b><b class="hidden font-medium tmu10-dark:inline">13.49:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">200</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t200"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t200">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.51:1</b><b class="hidden font-medium tmu10-dark:inline">10.36:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Decorative rule</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">300</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t300"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t300">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.12:1</b><b class="hidden font-medium tmu10-dark:inline">7.20:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none tmu10-dark:border-t-2 tmu10-dark:border-t-tmu10-ink">
<span class="absolute -top-2.5 right-0 hidden rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:inline">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">400</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t400"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t400">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.96:1</b><b class="hidden font-medium tmu10-dark:inline">4.98:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">500</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t500"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t500">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">4.07:1</b><b class="hidden font-medium tmu10-dark:inline">3.55:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none border-t-2 border-t-tmu10-ink tmu10-dark:border-t-0">
<span class="absolute -top-2.5 right-0 rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:hidden">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">600</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t600"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t600">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">5.85:1</b><b class="hidden font-medium tmu10-dark:inline">2.75:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">700</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t700"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t700">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">8.60:1</b><b class="hidden font-medium tmu10-dark:inline">1.95:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">800</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t800"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t800">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">12.99:1</b><b class="hidden font-medium tmu10-dark:inline">1.42:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">900</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t900"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t900">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">17.65:1</b><b class="hidden font-medium tmu10-dark:inline">1.18:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tmu10-ground: light-dark(#ffffff, #14171a);
--color-tmu10-ground: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-bg: light-dark(#ffffff, #14171a);
--color-tmu10-bg: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-ink: light-dark(#16191c, #e9ecee);
--color-tmu10-ink: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-ink-2: light-dark(#5d666e, #a1a9b0);
--color-tmu10-ink-2: light-dark(oklch(48% 0.012 250), oklch(73% 0.008 250));
--color-tmu10-line: light-dark(#cfd3d7, #343b41);
--color-tmu10-line: light-dark(oklch(85.5% 0.005 250), oklch(33.5% 0.009 250));
--color-tmu10-ok: light-dark(#16663d, #62c78f);
--color-tmu10-ok: light-dark(oklch(44% 0.11 155), oklch(78% 0.12 155));
--color-tmu10-bad: light-dark(#a32020, #f08a8a);
--color-tmu10-bad: light-dark(oklch(45% 0.18 25), oklch(74% 0.14 25));
--color-tmu10-acc: light-dark(#16191c, #e9ecee);
--color-tmu10-acc: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-t050: light-dark(#f6f7f8, #eef1f3);
--color-tmu10-t100: light-dark(#e7e9eb, #d8dde0);
--color-tmu10-t200: light-dark(#cfd3d7, #bcc3c8);
--color-tmu10-t300: light-dark(#adb3b9, #9aa3aa);
--color-tmu10-t400: light-dark(#8f979e, #7d868d);
--color-tmu10-t500: light-dark(#767f87, #656e75);
--color-tmu10-t600: light-dark(#5d666e, #545d64);
--color-tmu10-t700: light-dark(#454d54, #3f474d);
--color-tmu10-t800: light-dark(#2b3238, #2b3238);
--color-tmu10-t900: light-dark(#16191c, #1e2429);
--color-tmu10-ok-bg: color-mix(in oklab, var(--color-tmu10-ok) 12%, transparent);
--color-tmu10-bad-bg: color-mix(in oklab, var(--color-tmu10-bad) 12%, transparent);
--font-tmu10-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu10-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-10 {
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-10:has(#tmu10-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-10:has(#tmu10-theme:checked) {
color-scheme: light;
}
}
/* "Effective dark": dark OS without the toggle, or light OS with it. One variant for both. */
@custom-variant tmu10-dark {
@media (prefers-color-scheme: dark) {
.tmu-10:not(:has(#tmu10-theme:checked)) & {
@slot;
}
}
@media (prefers-color-scheme: light) {
.tmu-10:has(#tmu10-theme:checked) & {
@slot;
}
}
}
```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 Grayscale Palette with Enough Contrast
Source: https://codefronts.com/design-styles/tailwind-css-minimalist-ui/tailwind-grayscale-palette-contrast-ratio/
A ten-step neutral ramp with its measured contrast ratio printed against the active surface, and a verdict per step. Flip the theme and every ratio, verdict and the 4.5:1 floor marker swaps — driven by a custom tmu10-dark: variant that knows about both the OS preference and the toggle, so the table is honest in all four combinations.
## HTML
```html
<section class="tmu-10 relative w-full min-h-svh bg-tmu10-bg font-tmu10-ui text-tmu10-ink antialiased" aria-labelledby="tmu10-title">
<div class="absolute top-4 right-4 z-10">
<input id="tmu10-theme" type="checkbox" class="peer sr-only">
<label for="tmu10-theme" class="grid size-11 cursor-pointer place-items-center rounded-full border border-tmu10-line bg-tmu10-bg text-tmu10-ink-2 shadow-[0_1px_2px_rgb(0_0_0/0.06)] transition-[color,rotate] duration-300 hover:text-tmu10-ink peer-checked:rotate-180 peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-tmu10-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-[64rem] 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-tmu10-mono text-xs font-medium uppercase tracking-[0.14em] text-tmu10-ink-2"><span class="tabular-nums text-tmu10-acc">10</span><span aria-hidden="true" class="h-px w-6 bg-tmu10-line"></span>Contrast</p>
<h2 id="tmu10-title" class="text-[clamp(1.75rem,1.2rem+2vw,2.75rem)] font-semibold leading-[1.08] tracking-[-0.03em] text-balance">A grey is only minimal if it can be read</h2>
<p class="text-[1.0625rem] leading-relaxed text-tmu10-ink-2 text-pretty">Every step of the ramp, measured against the surface you are looking at right now. Switch the theme — the ratios, verdicts and the floor move with it.</p>
</header>
<div role="table" aria-labelledby="tmu10-cap" class="grid min-w-0 border-t border-tmu10-line">
<p id="tmu10-cap" class="py-3 font-tmu10-mono text-xs text-tmu10-ink-2"><span class="tmu10-dark:hidden">Ratios against the light surface #ffffff</span><span class="hidden tmu10-dark:inline">Ratios against the dark surface #14171a</span></p>
<div role="row" class="grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-2.5 font-tmu10-mono text-[0.6875rem] uppercase tracking-[0.1em] text-tmu10-ink-2">
<span role="columnheader">Step</span><span role="columnheader">Swatch</span><span role="columnheader">Sample</span><span role="columnheader" class="text-right">Ratio</span><span role="columnheader" class="col-[3/-1] sm:col-auto sm:justify-self-end">Verdict</span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">050</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t050"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t050">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.07:1</b><b class="hidden font-medium tmu10-dark:inline">16.28:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">100</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t100"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t100">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.22:1</b><b class="hidden font-medium tmu10-dark:inline">13.49:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">200</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t200"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t200">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">1.51:1</b><b class="hidden font-medium tmu10-dark:inline">10.36:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Decorative rule</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">300</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t300"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t300">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.12:1</b><b class="hidden font-medium tmu10-dark:inline">7.20:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none tmu10-dark:border-t-2 tmu10-dark:border-t-tmu10-ink">
<span class="absolute -top-2.5 right-0 hidden rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:inline">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">400</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t400"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t400">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">2.96:1</b><b class="hidden font-medium tmu10-dark:inline">4.98:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">500</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t500"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t500">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">4.07:1</b><b class="hidden font-medium tmu10-dark:inline">3.55:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Large text / borders</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none border-t-2 border-t-tmu10-ink tmu10-dark:border-t-0">
<span class="absolute -top-2.5 right-0 rounded-full bg-tmu10-ink px-2 font-tmu10-mono text-[0.625rem] font-semibold uppercase leading-[1.25rem] tracking-[0.08em] text-tmu10-bg tmu10-dark:hidden">4.5:1 floor</span><span role="cell" class="font-tmu10-mono font-medium tabular-nums">600</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t600"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t600">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">5.85:1</b><b class="hidden font-medium tmu10-dark:inline">2.75:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Body text floor</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>The classic fail</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">700</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t700"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t700">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">8.60:1</b><b class="hidden font-medium tmu10-dark:inline">1.95:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Secondary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-bad-bg px-2 py-0.5 font-semibold text-tmu10-bad"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Fails 1.4.11</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">800</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t800"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t800">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">12.99:1</b><b class="hidden font-medium tmu10-dark:inline">1.42:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Primary text</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
<div role="row" class="relative grid min-w-0 grid-cols-[2.75rem_3rem_minmax(0,1fr)_4.75rem] items-center gap-x-3 gap-y-2 sm:grid-cols-[3rem_4rem_minmax(0,1fr)_5rem_minmax(0,12rem)] border-b border-tmu10-line py-3 text-[0.8125rem] transition-colors duration-150 hover:bg-tmu10-t050/40 motion-reduce:transition-none">
<span role="cell" class="font-tmu10-mono font-medium tabular-nums">900</span>
<span role="cell"><i class="block h-7 w-full rounded-md border border-tmu10-line bg-tmu10-t900"></i></span>
<span role="cell" class="text-lg font-medium tracking-[-0.01em] text-tmu10-t900">Aa</span>
<span role="cell" class="text-right font-tmu10-mono font-medium tabular-nums"><b class="font-medium tmu10-dark:hidden">17.65:1</b><b class="hidden font-medium tmu10-dark:inline">1.18:1</b></span>
<span role="cell" class="col-[3/-1] min-w-0 text-xs sm:col-auto sm:justify-self-end"><span class="tmu10-dark:hidden"><span class="inline-flex items-center gap-1.5 rounded-full bg-tmu10-ok-bg px-2 py-0.5 font-semibold text-tmu10-ok"><svg class="size-3.5 flex-none" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5 13l4 4L19 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>Headings</span></span><span class="hidden tmu10-dark:inline"><span class="inline-flex items-center px-2 py-0.5 text-tmu10-ink-2">Surface only</span></span></span>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tmu10-ground: light-dark(#ffffff, #14171a);
--color-tmu10-ground: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-bg: light-dark(#ffffff, #14171a);
--color-tmu10-bg: light-dark(oklch(100% 0 0), oklch(19% 0.005 250));
--color-tmu10-ink: light-dark(#16191c, #e9ecee);
--color-tmu10-ink: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-ink-2: light-dark(#5d666e, #a1a9b0);
--color-tmu10-ink-2: light-dark(oklch(48% 0.012 250), oklch(73% 0.008 250));
--color-tmu10-line: light-dark(#cfd3d7, #343b41);
--color-tmu10-line: light-dark(oklch(85.5% 0.005 250), oklch(33.5% 0.009 250));
--color-tmu10-ok: light-dark(#16663d, #62c78f);
--color-tmu10-ok: light-dark(oklch(44% 0.11 155), oklch(78% 0.12 155));
--color-tmu10-bad: light-dark(#a32020, #f08a8a);
--color-tmu10-bad: light-dark(oklch(45% 0.18 25), oklch(74% 0.14 25));
--color-tmu10-acc: light-dark(#16191c, #e9ecee);
--color-tmu10-acc: light-dark(oklch(20% 0.006 250), oklch(93.5% 0.003 250));
--color-tmu10-t050: light-dark(#f6f7f8, #eef1f3);
--color-tmu10-t100: light-dark(#e7e9eb, #d8dde0);
--color-tmu10-t200: light-dark(#cfd3d7, #bcc3c8);
--color-tmu10-t300: light-dark(#adb3b9, #9aa3aa);
--color-tmu10-t400: light-dark(#8f979e, #7d868d);
--color-tmu10-t500: light-dark(#767f87, #656e75);
--color-tmu10-t600: light-dark(#5d666e, #545d64);
--color-tmu10-t700: light-dark(#454d54, #3f474d);
--color-tmu10-t800: light-dark(#2b3238, #2b3238);
--color-tmu10-t900: light-dark(#16191c, #1e2429);
--color-tmu10-ok-bg: color-mix(in oklab, var(--color-tmu10-ok) 12%, transparent);
--color-tmu10-bad-bg: color-mix(in oklab, var(--color-tmu10-bad) 12%, transparent);
--font-tmu10-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-tmu10-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-10 {
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-10:has(#tmu10-theme:checked) {
color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
.tmu-10:has(#tmu10-theme:checked) {
color-scheme: light;
}
}
/* "Effective dark": dark OS without the toggle, or light OS with it. One variant for both. */
@custom-variant tmu10-dark {
@media (prefers-color-scheme: dark) {
.tmu-10:not(:has(#tmu10-theme:checked)) & {
@slot;
}
}
@media (prefers-color-scheme: light) {
.tmu-10:has(#tmu10-theme:checked) & {
@slot;
}
}
}
```How this works
A neutral ramp is a contrast budget, not a set of greys you liked. Build it in oklch() and the lightness values are perceptually even, which means step 5 really does look halfway between step 1 and step 9 — something hex ramps almost never achieve. Then measure each step against the ground it will actually sit on and write the ratio down, because a ratio you have not measured is a ratio you are guessing.
The thresholds, exactly. SC 1.4.3 requires 4.5:1 for body text and 3:1 for large text, where large means 24px, or 18.66px if bold. SC 1.4.11 requires 3:1 for the boundary of any UI component and for graphical objects needed to understand content. That last one is the sleeper: a form input whose border sits at 1.8:1 against the page is a failure even if its label is perfect, because the boundary is what tells you the field exists.
Print the cut-off and treat it as structural. On the ramp below, the last step that clears 4.5:1 on white is marked with a rule. Anything below that line is a decorative tone: it can be a divider, a disabled state, a hover surface. It cannot be text a user must read. Making that line visible in the palette itself is what stops it from being negotiated away in a design review.
Minimalist dark mode is not inverted light mode. Flip a light ramp and you get pure white text on near-black, which halates and fatigues, plus mid-greys that now sit far too close to the surface. Rebuild the ramp: lift the darkest surface off pure black, pull the lightest ink back from pure white, and re-measure every pair. This demo ships two independent ramps — ten light steps measured against white, ten dark steps measured against a lifted near-black — and the printed ratio and verdict on every row switch with the theme, because the same step name does a different job in each. Toggle the theme and watch 600 go from the body-text floor to the classic fail. Both columns are measured against the resolved oklch() ground rather than the hex fallback, which is a 2% difference and exactly the kind of thing an asserted number gets wrong.
Make it yours
- Reuse
tmu10-dark:anywhere in the demo — it is a normal variant and stacks withhover:,sm:and the rest. - Replace the ramp with your own neutrals by editing
--color-tmu10-t050…t900, then re-measure and update the printed ratios. - Drop the dark column entirely for a light-only product — delete every
tmu10-dark:utility and the dark read-outs.
Gotchas — read before shipping
- Light grey secondary text at 2.8:1 is the signature minimalist accessibility failure. It reads as refined on a calibrated display in a dark room and is unreadable on a phone outdoors.
- Contrast is a ratio against a specific ground. A grey that passes on white fails on a light grey card, so measure against the surface the text actually sits on.
- Component boundaries are covered by SC 1.4.11 at 3:1. A hairline input border at 1.8:1 fails even when the label passes.
- Building a dark ramp by inverting the light one produces pure white on pure black plus mid-greys too close to the surface. Rebuild it and re-measure.
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.