12 / 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 OLED True Black Dark Mode Product Card
A product card for OLED panels, where an unlit pixel is genuinely off: the page is #000 and every layer above it climbs a short surface ramp — #0a0a0a, #141414, #1c1c1c — instead of relying on shadows a true-black substrate swallows. Finish swatches and a save toggle are pure-CSS state, and the card is pinned with scheme-only-dark so forced-dark tools leave it alone.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tdm-11 scheme-only-dark grid w-full min-h-svh place-items-center bg-tdm11-void bg-[radial-gradient(80%_55%_at_50%_0%,#0d0d0d,transparent_70%)] px-4 py-12 font-tdm11-sans text-tdm11-body antialiased">
<article class="grid w-full max-w-[60rem] overflow-hidden rounded-[30px] bg-tdm11-s0 inset-shadow-[0_1px_0_var(--color-tdm11-sheen)] ring-1 ring-tdm11-hair md:grid-cols-[1.05fr_1fr]">
<div class="relative m-3 overflow-hidden rounded-[22px] bg-tdm11-s1 md:mr-0">
<img src="https://picsum.photos/seed/oled-1024/900/900" width="900" height="900" alt="Halo desk lamp in anodised graphite — replace with your product photograph" loading="lazy" decoding="async" class="aspect-square size-full object-cover brightness-90 saturate-[.85]">
<span class="absolute top-3 left-3 inline-flex items-center gap-1.5 rounded-full bg-tdm11-void/70 px-3 py-1.5 font-tdm11-mono text-[11px] text-tdm11-ink ring-1 ring-tdm11-hair backdrop-blur-md"><svg class="size-3.5 text-tdm11-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 2.5 4.5 13.5H12l-1 8 8.5-11H12Z"/></svg>Power-optimised for OLED</span>
</div>
<div class="grid content-center gap-6 p-6 sm:p-9">
<div class="grid gap-2">
<p class="font-tdm11-mono text-[11px] uppercase tracking-[0.18em] text-tdm11-mut">Nocturne Series</p>
<h1 class="text-[clamp(1.8rem,3.4vw,2.5rem)] font-semibold tracking-[-0.04em] text-tdm11-ink">Halo Desk Lamp</h1>
<p class="max-w-[42ch] text-[15px]/relaxed text-pretty">Continuous 1800K–5000K dimming with a matte anodised shell. Reads beautifully against a true-black interface.</p>
</div>
<fieldset class="grid gap-2.5">
<legend class="mb-2.5 text-[13px] text-tdm11-mut">Finish</legend>
<div class="flex gap-2">
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Graphite"><input type="radio" name="tdm-11-finish" class="sr-only" checked><span class="sr-only">Graphite</span><span class="size-7 rounded-full bg-[#2a2a2a] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Silver"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Silver</span><span class="size-7 rounded-full bg-[#c9ccd1] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Brass"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Brass</span><span class="size-7 rounded-full bg-[#b99a5b] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
</div>
</fieldset>
<dl class="grid divide-y divide-tdm11-hair rounded-2xl bg-tdm11-s1 text-sm">
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Finish</dt><dd class="text-tdm11-ink">Anodised graphite</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Output</dt><dd class="text-tdm11-ink">420 lm · CRI 97</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Ships</dt><dd class="text-tdm11-ink">Free, 2–4 days</dd></div>
</dl>
<div class="flex flex-wrap items-center justify-between gap-4">
<p class="flex items-baseline gap-2"><span class="text-3xl font-semibold tracking-[-0.03em] text-tdm11-ink tabular-nums">$248</span><s class="text-sm text-tdm11-mut">$310</s><span class="rounded-md bg-tdm11-s2 px-1.5 py-0.5 font-tdm11-mono text-[11px] text-tdm11-acc">−20%</span></p>
<div class="flex gap-2">
<label class="group/save inline-flex min-h-12 cursor-pointer items-center gap-2 rounded-2xl bg-tdm11-s2 px-4 text-sm font-medium text-tdm11-ink transition hover:bg-tdm11-s3 has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc">
<input type="checkbox" class="sr-only"><svg class="size-[18px] transition group-has-checked/save:fill-current group-has-checked/save:text-tdm11-love" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7a4.3 4.3 0 0 1 7.5 3c0 5.4-7.5 10-7.5 10Z"/></svg><span class="group-has-checked/save:hidden">Save</span><span class="hidden group-has-checked/save:inline">Saved</span>
</label>
<button type="button" class="min-h-12 rounded-2xl bg-tdm11-acc px-6 text-sm font-semibold text-tdm11-acc-ink transition hover:-translate-y-px hover:bg-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm11-acc motion-reduce:transition-none">Add to bag</button>
</div>
</div>
</div>
</article>
</div><div class="tdm-11 scheme-only-dark grid w-full min-h-svh place-items-center bg-tdm11-void bg-[radial-gradient(80%_55%_at_50%_0%,#0d0d0d,transparent_70%)] px-4 py-12 font-tdm11-sans text-tdm11-body antialiased">
<article class="grid w-full max-w-[60rem] overflow-hidden rounded-[30px] bg-tdm11-s0 inset-shadow-[0_1px_0_var(--color-tdm11-sheen)] ring-1 ring-tdm11-hair md:grid-cols-[1.05fr_1fr]">
<div class="relative m-3 overflow-hidden rounded-[22px] bg-tdm11-s1 md:mr-0">
<img src="https://picsum.photos/seed/oled-1024/900/900" width="900" height="900" alt="Halo desk lamp in anodised graphite — replace with your product photograph" loading="lazy" decoding="async" class="aspect-square size-full object-cover brightness-90 saturate-[.85]">
<span class="absolute top-3 left-3 inline-flex items-center gap-1.5 rounded-full bg-tdm11-void/70 px-3 py-1.5 font-tdm11-mono text-[11px] text-tdm11-ink ring-1 ring-tdm11-hair backdrop-blur-md"><svg class="size-3.5 text-tdm11-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 2.5 4.5 13.5H12l-1 8 8.5-11H12Z"/></svg>Power-optimised for OLED</span>
</div>
<div class="grid content-center gap-6 p-6 sm:p-9">
<div class="grid gap-2">
<p class="font-tdm11-mono text-[11px] uppercase tracking-[0.18em] text-tdm11-mut">Nocturne Series</p>
<h1 class="text-[clamp(1.8rem,3.4vw,2.5rem)] font-semibold tracking-[-0.04em] text-tdm11-ink">Halo Desk Lamp</h1>
<p class="max-w-[42ch] text-[15px]/relaxed text-pretty">Continuous 1800K–5000K dimming with a matte anodised shell. Reads beautifully against a true-black interface.</p>
</div>
<fieldset class="grid gap-2.5">
<legend class="mb-2.5 text-[13px] text-tdm11-mut">Finish</legend>
<div class="flex gap-2">
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Graphite"><input type="radio" name="tdm-11-finish" class="sr-only" checked><span class="sr-only">Graphite</span><span class="size-7 rounded-full bg-[#2a2a2a] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Silver"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Silver</span><span class="size-7 rounded-full bg-[#c9ccd1] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Brass"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Brass</span><span class="size-7 rounded-full bg-[#b99a5b] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
</div>
</fieldset>
<dl class="grid divide-y divide-tdm11-hair rounded-2xl bg-tdm11-s1 text-sm">
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Finish</dt><dd class="text-tdm11-ink">Anodised graphite</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Output</dt><dd class="text-tdm11-ink">420 lm · CRI 97</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Ships</dt><dd class="text-tdm11-ink">Free, 2–4 days</dd></div>
</dl>
<div class="flex flex-wrap items-center justify-between gap-4">
<p class="flex items-baseline gap-2"><span class="text-3xl font-semibold tracking-[-0.03em] text-tdm11-ink tabular-nums">$248</span><s class="text-sm text-tdm11-mut">$310</s><span class="rounded-md bg-tdm11-s2 px-1.5 py-0.5 font-tdm11-mono text-[11px] text-tdm11-acc">−20%</span></p>
<div class="flex gap-2">
<label class="group/save inline-flex min-h-12 cursor-pointer items-center gap-2 rounded-2xl bg-tdm11-s2 px-4 text-sm font-medium text-tdm11-ink transition hover:bg-tdm11-s3 has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc">
<input type="checkbox" class="sr-only"><svg class="size-[18px] transition group-has-checked/save:fill-current group-has-checked/save:text-tdm11-love" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7a4.3 4.3 0 0 1 7.5 3c0 5.4-7.5 10-7.5 10Z"/></svg><span class="group-has-checked/save:hidden">Save</span><span class="hidden group-has-checked/save:inline">Saved</span>
</label>
<button type="button" class="min-h-12 rounded-2xl bg-tdm11-acc px-6 text-sm font-semibold text-tdm11-acc-ink transition hover:-translate-y-px hover:bg-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm11-acc motion-reduce:transition-none">Add to bag</button>
</div>
</div>
</div>
</article>
</div>@import "tailwindcss";
@theme {
--color-tdm11-void: #000000;
--color-tdm11-s0: #0a0a0a;
--color-tdm11-s1: #141414;
--color-tdm11-s2: #1c1c1c;
--color-tdm11-s3: #262626;
--color-tdm11-hair: rgb(255 255 255 / .08);
--color-tdm11-sheen: rgb(255 255 255 / .07);
--color-tdm11-ink: #fafafa;
--color-tdm11-body: #d4d4d4;
--color-tdm11-mut: #8f8f8f;
--color-tdm11-acc: #e8ecf2;
--color-tdm11-acc-ink: #050505;
--color-tdm11-love: #fb7185;
--font-tdm11-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm11-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-11 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tdm11-void: #000000;
--color-tdm11-s0: #0a0a0a;
--color-tdm11-s1: #141414;
--color-tdm11-s2: #1c1c1c;
--color-tdm11-s3: #262626;
--color-tdm11-hair: rgb(255 255 255 / .08);
--color-tdm11-sheen: rgb(255 255 255 / .07);
--color-tdm11-ink: #fafafa;
--color-tdm11-body: #d4d4d4;
--color-tdm11-mut: #8f8f8f;
--color-tdm11-acc: #e8ecf2;
--color-tdm11-acc-ink: #050505;
--color-tdm11-love: #fb7185;
--font-tdm11-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm11-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-11 {
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-tdm11-void: #000000;
--color-tdm11-s0: #0a0a0a;
--color-tdm11-s1: #141414;
--color-tdm11-s2: #1c1c1c;
--color-tdm11-s3: #262626;
--color-tdm11-hair: rgb(255 255 255 / .08);
--color-tdm11-sheen: rgb(255 255 255 / .07);
--color-tdm11-ink: #fafafa;
--color-tdm11-body: #d4d4d4;
--color-tdm11-mut: #8f8f8f;
--color-tdm11-acc: #e8ecf2;
--color-tdm11-acc-ink: #050505;
--color-tdm11-love: #fb7185;
--font-tdm11-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm11-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-11 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tdm11-void: #000000;
--color-tdm11-s0: #0a0a0a;
--color-tdm11-s1: #141414;
--color-tdm11-s2: #1c1c1c;
--color-tdm11-s3: #262626;
--color-tdm11-hair: rgb(255 255 255 / .08);
--color-tdm11-sheen: rgb(255 255 255 / .07);
--color-tdm11-ink: #fafafa;
--color-tdm11-body: #d4d4d4;
--color-tdm11-mut: #8f8f8f;
--color-tdm11-acc: #e8ecf2;
--color-tdm11-acc-ink: #050505;
--color-tdm11-love: #fb7185;
--font-tdm11-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm11-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-11 {
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.
- A dark-only demo, so tokens are plain colours — no
light-dark(). The root'scolor-scheme: darkbecamescheme-only-dark, which also opts out of Chrome's auto-dark. - The surface ramp mapped 1:1 to
bg-tdm11-s0/s1/s2; the hairline + sheen pair becamering-1 ring-tdm11-hairand aninset-shadow-*. - UI upgrade from the CSS original: a working finish picker (three radio swatches), a Save toggle that fills the heart and swaps its label, and a discount chip.
- UI upgrade: square image crop with a frosted badge, 48px actions, and muted copy lifted from
#8a8a8ato#8f8f8fon#0a0a0a(6.1: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 OLED True Black Dark Mode Product Card
Source: https://codefronts.com/design-styles/tailwind-css-dark-mode-ui/tailwind-oled-true-black-product-card/
A product card for OLED panels, where an unlit pixel is genuinely off: the page is #000 and every layer above it climbs a short surface ramp — #0a0a0a, #141414, #1c1c1c — instead of relying on shadows a true-black substrate swallows. Finish swatches and a save toggle are pure-CSS state, and the card is pinned with scheme-only-dark so forced-dark tools leave it alone.
## HTML
```html
<div class="tdm-11 scheme-only-dark grid w-full min-h-svh place-items-center bg-tdm11-void bg-[radial-gradient(80%_55%_at_50%_0%,#0d0d0d,transparent_70%)] px-4 py-12 font-tdm11-sans text-tdm11-body antialiased">
<article class="grid w-full max-w-[60rem] overflow-hidden rounded-[30px] bg-tdm11-s0 inset-shadow-[0_1px_0_var(--color-tdm11-sheen)] ring-1 ring-tdm11-hair md:grid-cols-[1.05fr_1fr]">
<div class="relative m-3 overflow-hidden rounded-[22px] bg-tdm11-s1 md:mr-0">
<img src="https://picsum.photos/seed/oled-1024/900/900" width="900" height="900" alt="Halo desk lamp in anodised graphite — replace with your product photograph" loading="lazy" decoding="async" class="aspect-square size-full object-cover brightness-90 saturate-[.85]">
<span class="absolute top-3 left-3 inline-flex items-center gap-1.5 rounded-full bg-tdm11-void/70 px-3 py-1.5 font-tdm11-mono text-[11px] text-tdm11-ink ring-1 ring-tdm11-hair backdrop-blur-md"><svg class="size-3.5 text-tdm11-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 2.5 4.5 13.5H12l-1 8 8.5-11H12Z"/></svg>Power-optimised for OLED</span>
</div>
<div class="grid content-center gap-6 p-6 sm:p-9">
<div class="grid gap-2">
<p class="font-tdm11-mono text-[11px] uppercase tracking-[0.18em] text-tdm11-mut">Nocturne Series</p>
<h1 class="text-[clamp(1.8rem,3.4vw,2.5rem)] font-semibold tracking-[-0.04em] text-tdm11-ink">Halo Desk Lamp</h1>
<p class="max-w-[42ch] text-[15px]/relaxed text-pretty">Continuous 1800K–5000K dimming with a matte anodised shell. Reads beautifully against a true-black interface.</p>
</div>
<fieldset class="grid gap-2.5">
<legend class="mb-2.5 text-[13px] text-tdm11-mut">Finish</legend>
<div class="flex gap-2">
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Graphite"><input type="radio" name="tdm-11-finish" class="sr-only" checked><span class="sr-only">Graphite</span><span class="size-7 rounded-full bg-[#2a2a2a] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Silver"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Silver</span><span class="size-7 rounded-full bg-[#c9ccd1] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Brass"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Brass</span><span class="size-7 rounded-full bg-[#b99a5b] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
</div>
</fieldset>
<dl class="grid divide-y divide-tdm11-hair rounded-2xl bg-tdm11-s1 text-sm">
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Finish</dt><dd class="text-tdm11-ink">Anodised graphite</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Output</dt><dd class="text-tdm11-ink">420 lm · CRI 97</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Ships</dt><dd class="text-tdm11-ink">Free, 2–4 days</dd></div>
</dl>
<div class="flex flex-wrap items-center justify-between gap-4">
<p class="flex items-baseline gap-2"><span class="text-3xl font-semibold tracking-[-0.03em] text-tdm11-ink tabular-nums">$248</span><s class="text-sm text-tdm11-mut">$310</s><span class="rounded-md bg-tdm11-s2 px-1.5 py-0.5 font-tdm11-mono text-[11px] text-tdm11-acc">−20%</span></p>
<div class="flex gap-2">
<label class="group/save inline-flex min-h-12 cursor-pointer items-center gap-2 rounded-2xl bg-tdm11-s2 px-4 text-sm font-medium text-tdm11-ink transition hover:bg-tdm11-s3 has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc">
<input type="checkbox" class="sr-only"><svg class="size-[18px] transition group-has-checked/save:fill-current group-has-checked/save:text-tdm11-love" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7a4.3 4.3 0 0 1 7.5 3c0 5.4-7.5 10-7.5 10Z"/></svg><span class="group-has-checked/save:hidden">Save</span><span class="hidden group-has-checked/save:inline">Saved</span>
</label>
<button type="button" class="min-h-12 rounded-2xl bg-tdm11-acc px-6 text-sm font-semibold text-tdm11-acc-ink transition hover:-translate-y-px hover:bg-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm11-acc motion-reduce:transition-none">Add to bag</button>
</div>
</div>
</div>
</article>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdm11-void: #000000;
--color-tdm11-s0: #0a0a0a;
--color-tdm11-s1: #141414;
--color-tdm11-s2: #1c1c1c;
--color-tdm11-s3: #262626;
--color-tdm11-hair: rgb(255 255 255 / .08);
--color-tdm11-sheen: rgb(255 255 255 / .07);
--color-tdm11-ink: #fafafa;
--color-tdm11-body: #d4d4d4;
--color-tdm11-mut: #8f8f8f;
--color-tdm11-acc: #e8ecf2;
--color-tdm11-acc-ink: #050505;
--color-tdm11-love: #fb7185;
--font-tdm11-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm11-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-11 {
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 OLED True Black Dark Mode Product Card
Source: https://codefronts.com/design-styles/tailwind-css-dark-mode-ui/tailwind-oled-true-black-product-card/
A product card for OLED panels, where an unlit pixel is genuinely off: the page is #000 and every layer above it climbs a short surface ramp — #0a0a0a, #141414, #1c1c1c — instead of relying on shadows a true-black substrate swallows. Finish swatches and a save toggle are pure-CSS state, and the card is pinned with scheme-only-dark so forced-dark tools leave it alone.
## HTML
```html
<div class="tdm-11 scheme-only-dark grid w-full min-h-svh place-items-center bg-tdm11-void bg-[radial-gradient(80%_55%_at_50%_0%,#0d0d0d,transparent_70%)] px-4 py-12 font-tdm11-sans text-tdm11-body antialiased">
<article class="grid w-full max-w-[60rem] overflow-hidden rounded-[30px] bg-tdm11-s0 inset-shadow-[0_1px_0_var(--color-tdm11-sheen)] ring-1 ring-tdm11-hair md:grid-cols-[1.05fr_1fr]">
<div class="relative m-3 overflow-hidden rounded-[22px] bg-tdm11-s1 md:mr-0">
<img src="https://picsum.photos/seed/oled-1024/900/900" width="900" height="900" alt="Halo desk lamp in anodised graphite — replace with your product photograph" loading="lazy" decoding="async" class="aspect-square size-full object-cover brightness-90 saturate-[.85]">
<span class="absolute top-3 left-3 inline-flex items-center gap-1.5 rounded-full bg-tdm11-void/70 px-3 py-1.5 font-tdm11-mono text-[11px] text-tdm11-ink ring-1 ring-tdm11-hair backdrop-blur-md"><svg class="size-3.5 text-tdm11-acc" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 2.5 4.5 13.5H12l-1 8 8.5-11H12Z"/></svg>Power-optimised for OLED</span>
</div>
<div class="grid content-center gap-6 p-6 sm:p-9">
<div class="grid gap-2">
<p class="font-tdm11-mono text-[11px] uppercase tracking-[0.18em] text-tdm11-mut">Nocturne Series</p>
<h1 class="text-[clamp(1.8rem,3.4vw,2.5rem)] font-semibold tracking-[-0.04em] text-tdm11-ink">Halo Desk Lamp</h1>
<p class="max-w-[42ch] text-[15px]/relaxed text-pretty">Continuous 1800K–5000K dimming with a matte anodised shell. Reads beautifully against a true-black interface.</p>
</div>
<fieldset class="grid gap-2.5">
<legend class="mb-2.5 text-[13px] text-tdm11-mut">Finish</legend>
<div class="flex gap-2">
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Graphite"><input type="radio" name="tdm-11-finish" class="sr-only" checked><span class="sr-only">Graphite</span><span class="size-7 rounded-full bg-[#2a2a2a] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Silver"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Silver</span><span class="size-7 rounded-full bg-[#c9ccd1] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
<label class="grid size-11 cursor-pointer place-items-center rounded-full ring-1 ring-tdm11-hair transition hover:ring-tdm11-mut has-checked:ring-2 has-checked:ring-tdm11-ink has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc" title="Brass"><input type="radio" name="tdm-11-finish" class="sr-only"><span class="sr-only">Brass</span><span class="size-7 rounded-full bg-[#b99a5b] shadow-[inset_0_1px_1px_rgb(255_255_255/.3)]"></span></label>
</div>
</fieldset>
<dl class="grid divide-y divide-tdm11-hair rounded-2xl bg-tdm11-s1 text-sm">
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Finish</dt><dd class="text-tdm11-ink">Anodised graphite</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Output</dt><dd class="text-tdm11-ink">420 lm · CRI 97</dd></div>
<div class="flex justify-between gap-4 px-4 py-3"><dt class="text-tdm11-mut">Ships</dt><dd class="text-tdm11-ink">Free, 2–4 days</dd></div>
</dl>
<div class="flex flex-wrap items-center justify-between gap-4">
<p class="flex items-baseline gap-2"><span class="text-3xl font-semibold tracking-[-0.03em] text-tdm11-ink tabular-nums">$248</span><s class="text-sm text-tdm11-mut">$310</s><span class="rounded-md bg-tdm11-s2 px-1.5 py-0.5 font-tdm11-mono text-[11px] text-tdm11-acc">−20%</span></p>
<div class="flex gap-2">
<label class="group/save inline-flex min-h-12 cursor-pointer items-center gap-2 rounded-2xl bg-tdm11-s2 px-4 text-sm font-medium text-tdm11-ink transition hover:bg-tdm11-s3 has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-tdm11-acc">
<input type="checkbox" class="sr-only"><svg class="size-[18px] transition group-has-checked/save:fill-current group-has-checked/save:text-tdm11-love" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20s-7.5-4.6-7.5-10A4.3 4.3 0 0 1 12 7a4.3 4.3 0 0 1 7.5 3c0 5.4-7.5 10-7.5 10Z"/></svg><span class="group-has-checked/save:hidden">Save</span><span class="hidden group-has-checked/save:inline">Saved</span>
</label>
<button type="button" class="min-h-12 rounded-2xl bg-tdm11-acc px-6 text-sm font-semibold text-tdm11-acc-ink transition hover:-translate-y-px hover:bg-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tdm11-acc motion-reduce:transition-none">Add to bag</button>
</div>
</div>
</div>
</article>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tdm11-void: #000000;
--color-tdm11-s0: #0a0a0a;
--color-tdm11-s1: #141414;
--color-tdm11-s2: #1c1c1c;
--color-tdm11-s3: #262626;
--color-tdm11-hair: rgb(255 255 255 / .08);
--color-tdm11-sheen: rgb(255 255 255 / .07);
--color-tdm11-ink: #fafafa;
--color-tdm11-body: #d4d4d4;
--color-tdm11-mut: #8f8f8f;
--color-tdm11-acc: #e8ecf2;
--color-tdm11-acc-ink: #050505;
--color-tdm11-love: #fb7185;
--font-tdm11-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
--font-tdm11-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-11 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
}
```How this works
Shadows die on black. A drop shadow is a darker region; on #000 there is nothing darker. Elevation comes from a four-step luminance ramp plus a 1px top sheen drawn with inset-shadow-[0_1px_0_var(--color-tdm11-sheen)].
Why the ramp is short. OLED smear — the purple trail when a near-black pixel switches fully off — is worst between #000 and very dark greys. Starting surfaces at #0a0a0a keeps moving content's pixels lit.
@theme {
--color-tdm11-void: #000000;
--color-tdm11-s0: #0a0a0a;
--color-tdm11-s1: #141414;
--color-tdm11-s2: #1c1c1c;
}Make it yours
- Swap the image
srcfor your product shot; keepbrightness-90so a bright photo doesn't flare on black. - Tint the ramp with a hue (
#0a0a0c…) for a cooler OLED theme. - Add more finishes by copying a swatch label — each is a radio.
Gotchas — read before shipping
- True black is a deliberate dark-only theme; don't use
#000as the dark half of a generallight-dark()system. - Hairlines at 8% white disappear on cheap panels — keep the ramp doing the heavy lifting.
scheme-only-darkalso darkens scrollbars and form controls — test any native<select>.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
No light-dark() here — the Tailwind v4 floor applies.