Pure TailwindMIT licensed

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.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

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>
@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.

1Load Tailwind
<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.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@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;
}
3Fonts used by this demooptional — skip if you have your own type stack
<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's color-scheme: dark became scheme-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 became ring-1 ring-tdm11-hair and an inset-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 #8a8a8a to #8f8f8f on #0a0a0a (6.1:1).
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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 src for your product shot; keep brightness-90 so 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 #000 as the dark half of a general light-dark() system.
  • Hairlines at 8% white disappear on cheap panels — keep the ramp doing the heavy lifting.
  • scheme-only-dark also darkens scrollbars and form controls — test any native <select>.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

No light-dark() here — the Tailwind v4 floor applies.

Techniques used in this demo

Search CodeFronts

Loading…