02 / 23
All 23 in 23 Tailwind CSS Dark Mode UI
- 01Fix the Dark Mode Flash (FOUC) in Tailwind CSS with an Inline Head Script
- 02Tailwind CSS Dark Mode with prefers-color-scheme (System Theme)
- 03Tailwind Dark Mode Toggle with data-theme Attribute Override
- 04Tailwind v4 Dark Mode Design Tokens with color-mix()
- 05Tailwind CSS light-dark() Dark Mode Without Media Queries
- 06Tailwind Dark Mode Sidebar Navigation Component
- 07Tailwind Dark Mode Dashboard Cards with Sparklines
- 08Tailwind Dark Mode Modal Dialog with Blurred Backdrop
- 09Accessible Tailwind Dark Mode Login Form with Focus Rings
- 10Tailwind Three-State Theme Switcher (System / Light / Dark)
- 11Tailwind Dark Mode Code Editor UI with Syntax Highlighting
- 12Tailwind OLED True Black Dark Mode Product Card
- 13Minimalist Tailwind Dark Mode Settings Panel
- 14Tailwind Dark Mode Delete Confirmation Dialog (Editorial)
- 15Tailwind Terminal UI Component — Retro Dark Console
- 16Tailwind Warm Dark Mode Writing Editor (Mocha Theme)
- 17Tailwind Dark Mode Blog Article Reading Layout
- 18Tailwind Dark Mode Elevation Layers — Layered Surface Card
- 19Tailwind Dark Mode File Manager Table
- 20Tailwind Dark Mode Vertical Timeline Changelog
- 21Tailwind Glowing Button Dark Mode Countdown Card
- 22Tailwind Aurora Gradient Dark Hero Section
- 23Tailwind Dark Mode Alert Card — Payment Failed Notification
Tailwind CSS Dark Mode with prefers-color-scheme (System Theme)
The baseline every other pattern builds on: the UI simply obeys the operating system. Each colour token is declared once in @theme as a light-dark() pair, and one utility — scheme-light-dark — hands the choice to the OS. Three panels render identical markup: a scheme-light reference, a scheme-dark reference, and a live panel that follows your system right now.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tdm-01 w-full min-h-svh bg-tdm01-bg bg-[radial-gradient(90%_60%_at_50%_-10%,var(--color-tdm01-glow),transparent_70%)] font-tdm01-sans text-tdm01-ink antialiased scheme-light-dark">
<!-- Pair with: <meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#09090b"> -->
<div class="mx-auto grid min-h-svh max-w-6xl content-center gap-8 px-5 py-14 sm:px-10">
<header class="flex flex-wrap items-end justify-between gap-5">
<div class="grid gap-2.5">
<p class="font-tdm01-mono text-[11px] uppercase tracking-[0.16em] text-tdm01-acc">prefers-color-scheme · scheme-light-dark</p>
<h1 class="text-[clamp(1.75rem,3.6vw,2.6rem)] font-semibold tracking-[-0.04em] text-balance">One token set, three renderings</h1>
<p class="max-w-[60ch] text-[15px]/relaxed text-pretty text-tdm01-mut">Every colour is a <code class="font-tdm01-mono text-[13px] text-tdm01-ink">light-dark()</code> pair in <code class="font-tdm01-mono text-[13px] text-tdm01-ink">@theme</code>. The reference panels pin their scheme; the live panel inherits it from your operating system.</p>
</div>
<p class="inline-flex min-h-10 items-center gap-2 rounded-full border border-tdm01-line bg-tdm01-surface px-4 font-tdm01-mono text-xs text-tdm01-mut">
<svg class="size-4 text-tdm01-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2.5" y="4" width="19" height="13" rx="2"/><path d="M8.5 20.5h7M12 17v3.5"/></svg>
Your OS reports <strong class="font-semibold text-tdm01-ink dark:hidden">light</strong><strong class="hidden font-semibold text-tdm01-ink dark:inline">dark</strong>
</p>
</header>
<div class="grid grid-cols-[repeat(auto-fit,minmax(16.5rem,1fr))] gap-4">
<section class="scheme-light grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced light">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced light</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-light</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class="scheme-dark grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced dark">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced dark</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-dark</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class=" grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink ring-2 ring-tdm01-acc/45 ring-offset-4 ring-offset-tdm01-bg" aria-label="Live · your OS">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Live · your OS</span><code class="normal-case tracking-normal text-tdm01-acc">inherited</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
</div>
<aside class="grid gap-4 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-5 sm:p-6">
<h3 class="text-[15px] font-semibold tracking-tight">What one token flips — swatches drawn by the tokens themselves</h3>
<dl class="grid gap-2 sm:grid-cols-2">
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">bg</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-light"></span>#ffffff<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-dark"></span>#09090b</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">surface</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-light"></span>#f6f6f7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-dark"></span>#121216</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">ink</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-light"></span>#0a0a0b<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-dark"></span>#f4f4f5</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">line</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-light"></span>#e3e3e7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-dark"></span>#26262c</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">acc</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-light"></span>#4f46e5<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-dark"></span>#8b8bff</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">dot</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-light"></span>#16a34a<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-dark"></span>#4ade80</dd>
</div>
</dl>
<p class="max-w-[68ch] text-[13.5px]/relaxed text-pretty text-tdm01-mut">No toggle ships here on purpose — this is the pure OS-driven baseline. Each pair of swatches is the <em>same</em> utility, <code class="font-tdm01-mono text-tdm01-ink">bg-tdm01-*</code>, under <code class="font-tdm01-mono text-tdm01-ink">scheme-light</code> and <code class="font-tdm01-mono text-tdm01-ink">scheme-dark</code>.</p>
</aside>
</div>
</div><div class="tdm-01 w-full min-h-svh bg-tdm01-bg bg-[radial-gradient(90%_60%_at_50%_-10%,var(--color-tdm01-glow),transparent_70%)] font-tdm01-sans text-tdm01-ink antialiased scheme-light-dark">
<!-- Pair with: <meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#09090b"> -->
<div class="mx-auto grid min-h-svh max-w-6xl content-center gap-8 px-5 py-14 sm:px-10">
<header class="flex flex-wrap items-end justify-between gap-5">
<div class="grid gap-2.5">
<p class="font-tdm01-mono text-[11px] uppercase tracking-[0.16em] text-tdm01-acc">prefers-color-scheme · scheme-light-dark</p>
<h1 class="text-[clamp(1.75rem,3.6vw,2.6rem)] font-semibold tracking-[-0.04em] text-balance">One token set, three renderings</h1>
<p class="max-w-[60ch] text-[15px]/relaxed text-pretty text-tdm01-mut">Every colour is a <code class="font-tdm01-mono text-[13px] text-tdm01-ink">light-dark()</code> pair in <code class="font-tdm01-mono text-[13px] text-tdm01-ink">@theme</code>. The reference panels pin their scheme; the live panel inherits it from your operating system.</p>
</div>
<p class="inline-flex min-h-10 items-center gap-2 rounded-full border border-tdm01-line bg-tdm01-surface px-4 font-tdm01-mono text-xs text-tdm01-mut">
<svg class="size-4 text-tdm01-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2.5" y="4" width="19" height="13" rx="2"/><path d="M8.5 20.5h7M12 17v3.5"/></svg>
Your OS reports <strong class="font-semibold text-tdm01-ink dark:hidden">light</strong><strong class="hidden font-semibold text-tdm01-ink dark:inline">dark</strong>
</p>
</header>
<div class="grid grid-cols-[repeat(auto-fit,minmax(16.5rem,1fr))] gap-4">
<section class="scheme-light grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced light">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced light</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-light</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class="scheme-dark grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced dark">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced dark</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-dark</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class=" grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink ring-2 ring-tdm01-acc/45 ring-offset-4 ring-offset-tdm01-bg" aria-label="Live · your OS">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Live · your OS</span><code class="normal-case tracking-normal text-tdm01-acc">inherited</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
</div>
<aside class="grid gap-4 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-5 sm:p-6">
<h3 class="text-[15px] font-semibold tracking-tight">What one token flips — swatches drawn by the tokens themselves</h3>
<dl class="grid gap-2 sm:grid-cols-2">
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">bg</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-light"></span>#ffffff<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-dark"></span>#09090b</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">surface</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-light"></span>#f6f6f7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-dark"></span>#121216</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">ink</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-light"></span>#0a0a0b<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-dark"></span>#f4f4f5</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">line</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-light"></span>#e3e3e7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-dark"></span>#26262c</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">acc</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-light"></span>#4f46e5<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-dark"></span>#8b8bff</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">dot</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-light"></span>#16a34a<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-dark"></span>#4ade80</dd>
</div>
</dl>
<p class="max-w-[68ch] text-[13.5px]/relaxed text-pretty text-tdm01-mut">No toggle ships here on purpose — this is the pure OS-driven baseline. Each pair of swatches is the <em>same</em> utility, <code class="font-tdm01-mono text-tdm01-ink">bg-tdm01-*</code>, under <code class="font-tdm01-mono text-tdm01-ink">scheme-light</code> and <code class="font-tdm01-mono text-tdm01-ink">scheme-dark</code>.</p>
</aside>
</div>
</div>@import "tailwindcss";
@theme {
--color-tdm01-bg: light-dark(#ffffff, #09090b);
--color-tdm01-glow: light-dark(#eef0ff, #15153a);
--color-tdm01-surface: light-dark(#f6f6f7, #121216);
--color-tdm01-raised: light-dark(#ffffff, #18181d);
--color-tdm01-ink: light-dark(#0a0a0b, #f4f4f5);
--color-tdm01-mut: light-dark(#55595f, #a1a1aa);
--color-tdm01-line: light-dark(#e3e3e7, #27272d);
--color-tdm01-acc: light-dark(#4f46e5, #8b8bff);
--color-tdm01-acc-ink: light-dark(#ffffff, #0a0a12);
--color-tdm01-focus: light-dark(#4f46e5, #a5b4fc);
--color-tdm01-dot: light-dark(#16a34a, #4ade80);
--shadow-tdm01-card: 0 1px 2px light-dark(rgb(9 9 11 / .08), rgb(0 0 0 / .5)), 0 18px 36px -24px light-dark(rgb(9 9 11 / .22), rgb(0 0 0 / .9));
--font-tdm01-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in utilities, so the stage is sized
in the moment before the browser build has compiled. */
.tdm-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tdm01-bg: light-dark(#ffffff, #09090b);
--color-tdm01-glow: light-dark(#eef0ff, #15153a);
--color-tdm01-surface: light-dark(#f6f6f7, #121216);
--color-tdm01-raised: light-dark(#ffffff, #18181d);
--color-tdm01-ink: light-dark(#0a0a0b, #f4f4f5);
--color-tdm01-mut: light-dark(#55595f, #a1a1aa);
--color-tdm01-line: light-dark(#e3e3e7, #27272d);
--color-tdm01-acc: light-dark(#4f46e5, #8b8bff);
--color-tdm01-acc-ink: light-dark(#ffffff, #0a0a12);
--color-tdm01-focus: light-dark(#4f46e5, #a5b4fc);
--color-tdm01-dot: light-dark(#16a34a, #4ade80);
--shadow-tdm01-card: 0 1px 2px light-dark(rgb(9 9 11 / .08), rgb(0 0 0 / .5)), 0 18px 36px -24px light-dark(rgb(9 9 11 / .22), rgb(0 0 0 / .9));
--font-tdm01-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in utilities, so the stage is sized
in the moment before the browser build has compiled. */
.tdm-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}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-tdm01-bg: light-dark(#ffffff, #09090b);
--color-tdm01-glow: light-dark(#eef0ff, #15153a);
--color-tdm01-surface: light-dark(#f6f6f7, #121216);
--color-tdm01-raised: light-dark(#ffffff, #18181d);
--color-tdm01-ink: light-dark(#0a0a0b, #f4f4f5);
--color-tdm01-mut: light-dark(#55595f, #a1a1aa);
--color-tdm01-line: light-dark(#e3e3e7, #27272d);
--color-tdm01-acc: light-dark(#4f46e5, #8b8bff);
--color-tdm01-acc-ink: light-dark(#ffffff, #0a0a12);
--color-tdm01-focus: light-dark(#4f46e5, #a5b4fc);
--color-tdm01-dot: light-dark(#16a34a, #4ade80);
--shadow-tdm01-card: 0 1px 2px light-dark(rgb(9 9 11 / .08), rgb(0 0 0 / .5)), 0 18px 36px -24px light-dark(rgb(9 9 11 / .22), rgb(0 0 0 / .9));
--font-tdm01-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in utilities, so the stage is sized
in the moment before the browser build has compiled. */
.tdm-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tdm01-bg: light-dark(#ffffff, #09090b);
--color-tdm01-glow: light-dark(#eef0ff, #15153a);
--color-tdm01-surface: light-dark(#f6f6f7, #121216);
--color-tdm01-raised: light-dark(#ffffff, #18181d);
--color-tdm01-ink: light-dark(#0a0a0b, #f4f4f5);
--color-tdm01-mut: light-dark(#55595f, #a1a1aa);
--color-tdm01-line: light-dark(#e3e3e7, #27272d);
--color-tdm01-acc: light-dark(#4f46e5, #8b8bff);
--color-tdm01-acc-ink: light-dark(#ffffff, #0a0a12);
--color-tdm01-focus: light-dark(#4f46e5, #a5b4fc);
--color-tdm01-dot: light-dark(#16a34a, #4ade80);
--shadow-tdm01-card: 0 1px 2px light-dark(rgb(9 9 11 / .08), rgb(0 0 0 / .5)), 0 18px 36px -24px light-dark(rgb(9 9 11 / .22), rgb(0 0 0 / .9));
--font-tdm01-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in utilities, so the stage is sized
in the moment before the browser build has compiled. */
.tdm-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@300..800&family=Geist+Mono:wght@400..600&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@300..800&family=Geist+Mono:wght@400..600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The light block, the
@media (prefers-color-scheme: dark)block and two--light/--darkmodifier blocks became one@themeblock oflight-dark()pairs plus threescheme-*utilities. - Forced reference panels cost one class each (
scheme-light,scheme-dark) instead of a re-declared token block. - UI upgrade from the CSS original: a live "Your OS reports …" pill (via
dark:), a ringed live panel so the reader knows which card is theirs, and token swatches drawn by the tokens themselves — no hard-coded inline backgrounds left to drift. - UI upgrade: Geist / Geist Mono replace system-ui, buttons grew to 44px, and light-mode muted ink darkened to
#55595f(7:1).
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 CSS Dark Mode with prefers-color-scheme (System Theme)
Source: https://codefronts.com/design-styles/tailwind-css-dark-mode-ui/tailwind-dark-mode-prefers-color-scheme/
The baseline every other pattern builds on: the UI simply obeys the operating system. Each colour token is declared once in @theme as a light-dark() pair, and one utility — scheme-light-dark — hands the choice to the OS. Three panels render identical markup: a scheme-light reference, a scheme-dark reference, and a live panel that follows your system right now.
## HTML
```html
<div class="tdm-01 w-full min-h-svh bg-tdm01-bg bg-[radial-gradient(90%_60%_at_50%_-10%,var(--color-tdm01-glow),transparent_70%)] font-tdm01-sans text-tdm01-ink antialiased scheme-light-dark">
<!-- Pair with: <meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#09090b"> -->
<div class="mx-auto grid min-h-svh max-w-6xl content-center gap-8 px-5 py-14 sm:px-10">
<header class="flex flex-wrap items-end justify-between gap-5">
<div class="grid gap-2.5">
<p class="font-tdm01-mono text-[11px] uppercase tracking-[0.16em] text-tdm01-acc">prefers-color-scheme · scheme-light-dark</p>
<h1 class="text-[clamp(1.75rem,3.6vw,2.6rem)] font-semibold tracking-[-0.04em] text-balance">One token set, three renderings</h1>
<p class="max-w-[60ch] text-[15px]/relaxed text-pretty text-tdm01-mut">Every colour is a <code class="font-tdm01-mono text-[13px] text-tdm01-ink">light-dark()</code> pair in <code class="font-tdm01-mono text-[13px] text-tdm01-ink">@theme</code>. The reference panels pin their scheme; the live panel inherits it from your operating system.</p>
</div>
<p class="inline-flex min-h-10 items-center gap-2 rounded-full border border-tdm01-line bg-tdm01-surface px-4 font-tdm01-mono text-xs text-tdm01-mut">
<svg class="size-4 text-tdm01-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2.5" y="4" width="19" height="13" rx="2"/><path d="M8.5 20.5h7M12 17v3.5"/></svg>
Your OS reports <strong class="font-semibold text-tdm01-ink dark:hidden">light</strong><strong class="hidden font-semibold text-tdm01-ink dark:inline">dark</strong>
</p>
</header>
<div class="grid grid-cols-[repeat(auto-fit,minmax(16.5rem,1fr))] gap-4">
<section class="scheme-light grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced light">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced light</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-light</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class="scheme-dark grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced dark">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced dark</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-dark</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class=" grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink ring-2 ring-tdm01-acc/45 ring-offset-4 ring-offset-tdm01-bg" aria-label="Live · your OS">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Live · your OS</span><code class="normal-case tracking-normal text-tdm01-acc">inherited</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
</div>
<aside class="grid gap-4 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-5 sm:p-6">
<h3 class="text-[15px] font-semibold tracking-tight">What one token flips — swatches drawn by the tokens themselves</h3>
<dl class="grid gap-2 sm:grid-cols-2">
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">bg</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-light"></span>#ffffff<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-dark"></span>#09090b</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">surface</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-light"></span>#f6f6f7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-dark"></span>#121216</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">ink</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-light"></span>#0a0a0b<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-dark"></span>#f4f4f5</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">line</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-light"></span>#e3e3e7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-dark"></span>#26262c</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">acc</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-light"></span>#4f46e5<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-dark"></span>#8b8bff</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">dot</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-light"></span>#16a34a<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-dark"></span>#4ade80</dd>
</div>
</dl>
<p class="max-w-[68ch] text-[13.5px]/relaxed text-pretty text-tdm01-mut">No toggle ships here on purpose — this is the pure OS-driven baseline. Each pair of swatches is the <em>same</em> utility, <code class="font-tdm01-mono text-tdm01-ink">bg-tdm01-*</code>, under <code class="font-tdm01-mono text-tdm01-ink">scheme-light</code> and <code class="font-tdm01-mono text-tdm01-ink">scheme-dark</code>.</p>
</aside>
</div>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdm01-bg: light-dark(#ffffff, #09090b);
--color-tdm01-glow: light-dark(#eef0ff, #15153a);
--color-tdm01-surface: light-dark(#f6f6f7, #121216);
--color-tdm01-raised: light-dark(#ffffff, #18181d);
--color-tdm01-ink: light-dark(#0a0a0b, #f4f4f5);
--color-tdm01-mut: light-dark(#55595f, #a1a1aa);
--color-tdm01-line: light-dark(#e3e3e7, #27272d);
--color-tdm01-acc: light-dark(#4f46e5, #8b8bff);
--color-tdm01-acc-ink: light-dark(#ffffff, #0a0a12);
--color-tdm01-focus: light-dark(#4f46e5, #a5b4fc);
--color-tdm01-dot: light-dark(#16a34a, #4ade80);
--shadow-tdm01-card: 0 1px 2px light-dark(rgb(9 9 11 / .08), rgb(0 0 0 / .5)), 0 18px 36px -24px light-dark(rgb(9 9 11 / .22), rgb(0 0 0 / .9));
--font-tdm01-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in utilities, so the stage is sized
in the moment before the browser build has compiled. */
.tdm-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}
```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 CSS Dark Mode with prefers-color-scheme (System Theme)
Source: https://codefronts.com/design-styles/tailwind-css-dark-mode-ui/tailwind-dark-mode-prefers-color-scheme/
The baseline every other pattern builds on: the UI simply obeys the operating system. Each colour token is declared once in @theme as a light-dark() pair, and one utility — scheme-light-dark — hands the choice to the OS. Three panels render identical markup: a scheme-light reference, a scheme-dark reference, and a live panel that follows your system right now.
## HTML
```html
<div class="tdm-01 w-full min-h-svh bg-tdm01-bg bg-[radial-gradient(90%_60%_at_50%_-10%,var(--color-tdm01-glow),transparent_70%)] font-tdm01-sans text-tdm01-ink antialiased scheme-light-dark">
<!-- Pair with: <meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#09090b"> -->
<div class="mx-auto grid min-h-svh max-w-6xl content-center gap-8 px-5 py-14 sm:px-10">
<header class="flex flex-wrap items-end justify-between gap-5">
<div class="grid gap-2.5">
<p class="font-tdm01-mono text-[11px] uppercase tracking-[0.16em] text-tdm01-acc">prefers-color-scheme · scheme-light-dark</p>
<h1 class="text-[clamp(1.75rem,3.6vw,2.6rem)] font-semibold tracking-[-0.04em] text-balance">One token set, three renderings</h1>
<p class="max-w-[60ch] text-[15px]/relaxed text-pretty text-tdm01-mut">Every colour is a <code class="font-tdm01-mono text-[13px] text-tdm01-ink">light-dark()</code> pair in <code class="font-tdm01-mono text-[13px] text-tdm01-ink">@theme</code>. The reference panels pin their scheme; the live panel inherits it from your operating system.</p>
</div>
<p class="inline-flex min-h-10 items-center gap-2 rounded-full border border-tdm01-line bg-tdm01-surface px-4 font-tdm01-mono text-xs text-tdm01-mut">
<svg class="size-4 text-tdm01-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2.5" y="4" width="19" height="13" rx="2"/><path d="M8.5 20.5h7M12 17v3.5"/></svg>
Your OS reports <strong class="font-semibold text-tdm01-ink dark:hidden">light</strong><strong class="hidden font-semibold text-tdm01-ink dark:inline">dark</strong>
</p>
</header>
<div class="grid grid-cols-[repeat(auto-fit,minmax(16.5rem,1fr))] gap-4">
<section class="scheme-light grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced light">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced light</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-light</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class="scheme-dark grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink " aria-label="Forced dark">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Forced dark</span><code class="normal-case tracking-normal text-tdm01-acc">scheme-dark</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
<section class=" grid content-start gap-3 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-3 text-tdm01-ink ring-2 ring-tdm01-acc/45 ring-offset-4 ring-offset-tdm01-bg" aria-label="Live · your OS">
<p class="flex items-center justify-between gap-2 px-1.5 pt-1 font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut"><span>Live · your OS</span><code class="normal-case tracking-normal text-tdm01-acc">inherited</code></p>
<article class="grid gap-2.5 rounded-2xl border border-tdm01-line bg-tdm01-raised p-4 shadow-tdm01-card">
<div class="flex items-center gap-2">
<span class="size-2 rounded-full bg-tdm01-dot ring-4 ring-tdm01-dot/20" aria-hidden="true"></span>
<span class="font-tdm01-mono text-[11px] uppercase tracking-[0.1em] text-tdm01-mut">Deploy · Ready</span>
</div>
<h2 class="font-tdm01-mono text-[17px] font-semibold tracking-tight">edge-runtime v4.2</h2>
<p class="text-sm/relaxed text-pretty text-tdm01-mut">Promoted to production 14 minutes ago by Alex Chen.</p>
<div class="mt-1 flex items-center justify-between gap-3">
<button type="button" class="inline-flex min-h-11 items-center gap-2 rounded-xl bg-tdm01-acc px-4 text-sm font-medium text-tdm01-acc-ink transition duration-200 hover:-translate-y-px hover:brightness-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm01-focus motion-reduce:transition-none forced-colors:border forced-colors:border-[ButtonText]">View build <svg class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 5.5l6.5 6.5-6.5 6.5"/></svg></button>
<span class="font-tdm01-mono text-xs text-tdm01-mut">iad1</span>
</div>
</article>
</section>
</div>
<aside class="grid gap-4 rounded-[22px] border border-tdm01-line bg-tdm01-surface p-5 sm:p-6">
<h3 class="text-[15px] font-semibold tracking-tight">What one token flips — swatches drawn by the tokens themselves</h3>
<dl class="grid gap-2 sm:grid-cols-2">
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">bg</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-light"></span>#ffffff<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-bg scheme-dark"></span>#09090b</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">surface</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-light"></span>#f6f6f7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-surface scheme-dark"></span>#121216</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">ink</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-light"></span>#0a0a0b<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-ink scheme-dark"></span>#f4f4f5</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">line</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-light"></span>#e3e3e7<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-line scheme-dark"></span>#26262c</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">acc</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-light"></span>#4f46e5<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-acc scheme-dark"></span>#8b8bff</dd>
</div>
<div class="grid grid-cols-[5.5rem_1fr] items-center gap-3 rounded-xl border border-tdm01-line bg-tdm01-bg px-3 py-2.5">
<dt class="font-tdm01-mono text-[13px] text-tdm01-acc">dot</dt>
<dd class="flex flex-wrap items-center gap-2 font-tdm01-mono text-xs text-tdm01-mut"><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-light"></span>#16a34a<span class="px-1 text-tdm01-ink" aria-hidden="true">→</span><span class="size-4 rounded-md border border-tdm01-line bg-tdm01-dot scheme-dark"></span>#4ade80</dd>
</div>
</dl>
<p class="max-w-[68ch] text-[13.5px]/relaxed text-pretty text-tdm01-mut">No toggle ships here on purpose — this is the pure OS-driven baseline. Each pair of swatches is the <em>same</em> utility, <code class="font-tdm01-mono text-tdm01-ink">bg-tdm01-*</code>, under <code class="font-tdm01-mono text-tdm01-ink">scheme-light</code> and <code class="font-tdm01-mono text-tdm01-ink">scheme-dark</code>.</p>
</aside>
</div>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdm01-bg: light-dark(#ffffff, #09090b);
--color-tdm01-glow: light-dark(#eef0ff, #15153a);
--color-tdm01-surface: light-dark(#f6f6f7, #121216);
--color-tdm01-raised: light-dark(#ffffff, #18181d);
--color-tdm01-ink: light-dark(#0a0a0b, #f4f4f5);
--color-tdm01-mut: light-dark(#55595f, #a1a1aa);
--color-tdm01-line: light-dark(#e3e3e7, #27272d);
--color-tdm01-acc: light-dark(#4f46e5, #8b8bff);
--color-tdm01-acc-ink: light-dark(#ffffff, #0a0a12);
--color-tdm01-focus: light-dark(#4f46e5, #a5b4fc);
--color-tdm01-dot: light-dark(#16a34a, #4ade80);
--shadow-tdm01-card: 0 1px 2px light-dark(rgb(9 9 11 / .08), rgb(0 0 0 / .5)), 0 18px 36px -24px light-dark(rgb(9 9 11 / .22), rgb(0 0 0 / .9));
--font-tdm01-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm01-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in utilities, so the stage is sized
in the moment before the browser build has compiled. */
.tdm-01 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}
```How this works
The token is the theme. The CSS original declared a light block and re-declared it inside @media (prefers-color-scheme: dark). In v4 the pair lives in a single @theme entry:
@theme {
--color-tdm01-bg: light-dark(#ffffff, #09090b);
--color-tdm01-acc: light-dark(#4f46e5, #8b8bff);
}bg-tdm01-bg compiles to background-color: var(--color-tdm01-bg), and light-dark() resolves against the element's used color-scheme. Put scheme-light-dark on the root and the browser picks from the OS; put scheme-dark on any descendant and that subtree is dark, whatever the OS says.
Why not bg-white dark:bg-zinc-950? That pattern doubles every class list and cannot force one panel light on a dark page. Semantic tokens keep the markup single-valued — dark: survives here only to print which theme your OS reports.
Make it yours
- Re-theme: edit the pairs in
@theme; the first value is light, the second dark. - Lift dark accents in lightness and drop their chroma —
#4f46e5passes on white but fails on near-black, so the pair flips to#8b8bff. - Add
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#09090b">so mobile browser chrome matches.
Gotchas — read before shipping
light-dark()only accepts colours — lengths, images anddisplaystill need thedark:variant.- Without
scheme-light-dark(orcolor-schemeon an ancestor) everylight-dark()resolves to its light value. - Tailwind emits only the theme variables a utility uses; a token referenced only from another stylesheet needs
@theme static.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 123+ | 17.5+ | 120+ | 123+ |
light-dark() is Baseline 2024; the Tailwind v4 sheet itself needs Chrome 111 / Safari 16.4 / Firefox 128.