Pure TailwindMIT licensed

Tailwind Dark-Mode Gadget Product Card with Accent Glow

A near-black card with a cool-grey edge and a cyan bloom that grows on hover — tuned so it reads on charcoal and on true-black OLED alike. Every coloured pixel derives from one --color-tpc08-acc token through color-mix() in arbitrary values, so retinting the card for gaming violet or crypto green is a one-line edit.

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

<section class="tpc-08 w-full min-h-svh grid place-items-center font-tpc08-sans px-5 py-14 bg-[radial-gradient(120%_120%_at_50%_20%,oklch(0.2_0.015_235),oklch(0.12_0.01_260))]" aria-label="Dark-mode gadget product card demo">
  <article class="group w-80 max-w-full rounded-[18px] overflow-hidden bg-linear-[180deg,var(--color-tpc08-card),var(--color-tpc08-card2)] border border-tpc08-edge shadow-[0_30px_60px_-34px_oklch(0_0_0/0.9)] transition-[translate,box-shadow,border-color] duration-350 hover:-translate-y-1 hover:border-[color-mix(in_oklch,var(--color-tpc08-acc)_45%,var(--color-tpc08-edge))] hover:shadow-[0_34px_70px_-34px_oklch(0_0_0/0.9),0_0_40px_-12px_color-mix(in_oklch,var(--color-tpc08-acc)_60%,transparent)] focus-within:-translate-y-1 focus-within:border-[color-mix(in_oklch,var(--color-tpc08-acc)_45%,var(--color-tpc08-edge))] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
    <div class="relative aspect-[16/11]">
      <div role="img" aria-label="Product photo: Vantage Pro wireless mouse" class="absolute inset-0 bg-linear-[135deg,var(--color-tpc08-ph),var(--color-tpc08-ph2)] bg-[url('https://images.unsplash.com/photo-1615663245857-ac93bb7c39e7?w=800&h=550&fit=crop&q=70')] bg-cover bg-center"></div>
      <span class="absolute top-3 left-3 px-3 py-[5px] rounded-full font-tpc08-mono text-[10px] tracking-[0.14em] uppercase text-tpc08-acc bg-[color-mix(in_oklch,var(--color-tpc08-acc)_14%,var(--color-tpc08-card2))] border border-[color-mix(in_oklch,var(--color-tpc08-acc)_40%,transparent)] shadow-[0_0_16px_-4px_var(--color-tpc08-acc)]">In stock</span>
    </div>
    <div class="px-5.5 pt-5 pb-5.5">
      <p class="font-tpc08-mono text-[11px] tracking-[0.2em] uppercase text-tpc08-mut">Vantage</p>
      <h3 class="mt-1.5 text-[18px] font-semibold leading-[1.3] text-tpc08-ink text-pretty">Vantage Pro Wireless Mouse</h3>
      <p class="mt-2 text-[13px] text-tpc08-mut2 tabular-nums">26K DPI &middot; 74g &middot; 90h battery</p>
      <div class="mt-4.5 flex items-center justify-between gap-3">
        <p class="text-[22px] font-extrabold text-tpc08-hi tabular-nums [text-shadow:0_0_18px_color-mix(in_oklch,var(--color-tpc08-acc)_45%,transparent)]">$99</p>
        <button type="button" class="min-h-11 h-11 px-5.5 rounded-xl border-0 bg-tpc08-acc text-tpc08-onacc text-sm font-bold cursor-pointer shadow-[0_0_22px_-6px_var(--color-tpc08-acc)] transition-[filter,scale] duration-200 hover:brightness-110 active:scale-97 focus-visible:outline-3 focus-visible:outline-[color-mix(in_oklch,var(--color-tpc08-acc)_55%,oklch(0_0_0))] focus-visible:outline-offset-2 motion-reduce:transition-none">Add to Cart</button>
      </div>
    </div>
  </article>
</section>
@import "tailwindcss";

@theme {
  --color-tpc08-card: #12161b;
  --color-tpc08-card: oklch(0.19 0.012 235);
  --color-tpc08-card2: #0c0f13;
  --color-tpc08-card2: oklch(0.15 0.01 235);
  --color-tpc08-edge: #1e252c;
  --color-tpc08-edge: oklch(0.25 0.012 235);
  --color-tpc08-ph: #1a2027;
  --color-tpc08-ph: oklch(0.23 0.013 235);
  --color-tpc08-ph2: #11161b;
  --color-tpc08-ph2: oklch(0.18 0.012 235);
  --color-tpc08-ink: #eef4f8;
  --color-tpc08-ink: oklch(0.95 0.008 235);
  --color-tpc08-hi: #ffffff;
  --color-tpc08-hi: oklch(1 0 0);
  --color-tpc08-mut: #8fa0ab;
  --color-tpc08-mut: oklch(0.7 0.018 235);
  --color-tpc08-mut2: #a3b3c0;
  --color-tpc08-mut2: oklch(0.76 0.02 235);
  --color-tpc08-acc: #6fd8ee;
  --color-tpc08-acc: oklch(0.82 0.16 195);
  --color-tpc08-onacc: #04141a;
  --color-tpc08-onacc: oklch(0.16 0.02 220);
  --font-tpc08-sans: 'Space Grotesk', system-ui, sans-serif;
  --font-tpc08-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tpc-08 {
  width: 100%;
  min-height: 100svh;
}

.tpc-08 ::selection {
  background: var(--color-tpc08-acc);
  color: var(--color-tpc08-onacc);
}

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-tpc08-card: #12161b;
  --color-tpc08-card: oklch(0.19 0.012 235);
  --color-tpc08-card2: #0c0f13;
  --color-tpc08-card2: oklch(0.15 0.01 235);
  --color-tpc08-edge: #1e252c;
  --color-tpc08-edge: oklch(0.25 0.012 235);
  --color-tpc08-ph: #1a2027;
  --color-tpc08-ph: oklch(0.23 0.013 235);
  --color-tpc08-ph2: #11161b;
  --color-tpc08-ph2: oklch(0.18 0.012 235);
  --color-tpc08-ink: #eef4f8;
  --color-tpc08-ink: oklch(0.95 0.008 235);
  --color-tpc08-hi: #ffffff;
  --color-tpc08-hi: oklch(1 0 0);
  --color-tpc08-mut: #8fa0ab;
  --color-tpc08-mut: oklch(0.7 0.018 235);
  --color-tpc08-mut2: #a3b3c0;
  --color-tpc08-mut2: oklch(0.76 0.02 235);
  --color-tpc08-acc: #6fd8ee;
  --color-tpc08-acc: oklch(0.82 0.16 195);
  --color-tpc08-onacc: #04141a;
  --color-tpc08-onacc: oklch(0.16 0.02 220);
  --font-tpc08-sans: 'Space Grotesk', system-ui, sans-serif;
  --font-tpc08-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tpc-08 {
  width: 100%;
  min-height: 100svh;
}

.tpc-08 ::selection {
  background: var(--color-tpc08-acc);
  color: var(--color-tpc08-onacc);
}
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=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • Six color-mix() derivations that lived in a stylesheet now sit on the elements they colour. The class lists are long, but the mix ratio is readable exactly where it matters, and the single-token retint still works.
  • The hover bloom and the ambient shadow are one arbitrary value with two layers. Tailwind's shadow-* scale cannot express 'this specific black plus this specific coloured spread', and it should not try.
  • [text-shadow:…] is arbitrary because v4 ships text-shadow-* only as a small scale — a coloured accent glow on a price is not on it.
  • The --color-tpc08-mut greys were both lightened from the original (#67757f and #8090a0); re-expressed in oklch it was obvious they sat under 4.5:1 on the card surface.
  • Enhancement over the CSS original: focus-within: twins for the whole lift, an active:scale-97 press on the CTA, and a vertical surface gradient so the card reads as an object rather than a cut-out.
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 Dark-Mode Gadget Product Card with Accent Glow
Source: https://codefronts.com/components/tailwind-css-product-cards/tailwind-dark-mode-gadget-product-card-glow/

A near-black card with a cool-grey edge and a cyan bloom that grows on hover — tuned so it reads on charcoal and on true-black OLED alike. Every coloured pixel derives from one --color-tpc08-acc token through color-mix() in arbitrary values, so retinting the card for gaming violet or crypto green is a one-line edit.
## HTML
```html
<section class="tpc-08 w-full min-h-svh grid place-items-center font-tpc08-sans px-5 py-14 bg-[radial-gradient(120%_120%_at_50%_20%,oklch(0.2_0.015_235),oklch(0.12_0.01_260))]" aria-label="Dark-mode gadget product card demo">
  <article class="group w-80 max-w-full rounded-[18px] overflow-hidden bg-linear-[180deg,var(--color-tpc08-card),var(--color-tpc08-card2)] border border-tpc08-edge shadow-[0_30px_60px_-34px_oklch(0_0_0/0.9)] transition-[translate,box-shadow,border-color] duration-350 hover:-translate-y-1 hover:border-[color-mix(in_oklch,var(--color-tpc08-acc)_45%,var(--color-tpc08-edge))] hover:shadow-[0_34px_70px_-34px_oklch(0_0_0/0.9),0_0_40px_-12px_color-mix(in_oklch,var(--color-tpc08-acc)_60%,transparent)] focus-within:-translate-y-1 focus-within:border-[color-mix(in_oklch,var(--color-tpc08-acc)_45%,var(--color-tpc08-edge))] motion-reduce:transition-none motion-reduce:hover:translate-y-0">
    <div class="relative aspect-[16/11]">
      <div role="img" aria-label="Product photo: Vantage Pro wireless mouse" class="absolute inset-0 bg-linear-[135deg,var(--color-tpc08-ph),var(--color-tpc08-ph2)] bg-[url('https://images.unsplash.com/photo-1615663245857-ac93bb7c39e7?w=800&h=550&fit=crop&q=70')] bg-cover bg-center"></div>
      <span class="absolute top-3 left-3 px-3 py-[5px] rounded-full font-tpc08-mono text-[10px] tracking-[0.14em] uppercase text-tpc08-acc bg-[color-mix(in_oklch,var(--color-tpc08-acc)_14%,var(--color-tpc08-card2))] border border-[color-mix(in_oklch,var(--color-tpc08-acc)_40%,transparent)] shadow-[0_0_16px_-4px_var(--color-tpc08-acc)]">In stock</span>
    </div>
    <div class="px-5.5 pt-5 pb-5.5">
      <p class="font-tpc08-mono text-[11px] tracking-[0.2em] uppercase text-tpc08-mut">Vantage</p>
      <h3 class="mt-1.5 text-[18px] font-semibold leading-[1.3] text-tpc08-ink text-pretty">Vantage Pro Wireless Mouse</h3>
      <p class="mt-2 text-[13px] text-tpc08-mut2 tabular-nums">26K DPI &middot; 74g &middot; 90h battery</p>
      <div class="mt-4.5 flex items-center justify-between gap-3">
        <p class="text-[22px] font-extrabold text-tpc08-hi tabular-nums [text-shadow:0_0_18px_color-mix(in_oklch,var(--color-tpc08-acc)_45%,transparent)]">$99</p>
        <button type="button" class="min-h-11 h-11 px-5.5 rounded-xl border-0 bg-tpc08-acc text-tpc08-onacc text-sm font-bold cursor-pointer shadow-[0_0_22px_-6px_var(--color-tpc08-acc)] transition-[filter,scale] duration-200 hover:brightness-110 active:scale-97 focus-visible:outline-3 focus-visible:outline-[color-mix(in_oklch,var(--color-tpc08-acc)_55%,oklch(0_0_0))] focus-visible:outline-offset-2 motion-reduce:transition-none">Add to Cart</button>
      </div>
    </div>
  </article>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tpc08-card: #12161b;
  --color-tpc08-card: oklch(0.19 0.012 235);
  --color-tpc08-card2: #0c0f13;
  --color-tpc08-card2: oklch(0.15 0.01 235);
  --color-tpc08-edge: #1e252c;
  --color-tpc08-edge: oklch(0.25 0.012 235);
  --color-tpc08-ph: #1a2027;
  --color-tpc08-ph: oklch(0.23 0.013 235);
  --color-tpc08-ph2: #11161b;
  --color-tpc08-ph2: oklch(0.18 0.012 235);
  --color-tpc08-ink: #eef4f8;
  --color-tpc08-ink: oklch(0.95 0.008 235);
  --color-tpc08-hi: #ffffff;
  --color-tpc08-hi: oklch(1 0 0);
  --color-tpc08-mut: #8fa0ab;
  --color-tpc08-mut: oklch(0.7 0.018 235);
  --color-tpc08-mut2: #a3b3c0;
  --color-tpc08-mut2: oklch(0.76 0.02 235);
  --color-tpc08-acc: #6fd8ee;
  --color-tpc08-acc: oklch(0.82 0.16 195);
  --color-tpc08-onacc: #04141a;
  --color-tpc08-onacc: oklch(0.16 0.02 220);
  --font-tpc08-sans: 'Space Grotesk', system-ui, sans-serif;
  --font-tpc08-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tpc-08 {
  width: 100%;
  min-height: 100svh;
}

.tpc-08 ::selection {
  background: var(--color-tpc08-acc);
  color: var(--color-tpc08-onacc);
}
```

How this works

One token, six derivations. The pill alone reads the accent three times — as 14%-mixed fill, 40%-mixed border and a raw glow:

class="text-tpc08-acc
       bg-[color-mix(in_oklch,var(--color-tpc08-acc)_14%,var(--color-tpc08-card2))]
       border-[color-mix(in_oklch,var(--color-tpc08-acc)_40%,transparent)]
       shadow-[0_0_16px_-4px_var(--color-tpc08-acc)]"

Long, but honest: each mix ratio is visible on the element it colours, and changing the token retints all six at once.

Why the surface is a gradient. A single dark fill on a dark page reads as absence. The card is bg-linear-[180deg,…] between two tokens four percent apart in lightness, which is enough to make it read as a surface with a top.

Glow discipline. The bloom is -12px spread and only appears on group-hover:, so at rest the card pays no shadow cost. On a catalog page that is the difference between a smooth scroll and a paint-bound one.

Make it yours

  • Retint everything from --color-tpc08-acc: cyan (here) for tech, oklch(0.78 0.18 145) for crypto, oklch(0.7 0.2 300) for gaming.
  • Bloom intensity: the blur and spread in the group-hover:shadow-[…] second layer.
  • Neon edge: swap the grey border-tpc08-edge for a low-percentage accent mix at rest, not just on hover.
  • Add a spec row (chipset, polling rate) under the name for a hardware-listing variant — the body is a plain block.
  • Surface depth: widen the two --color-tpc08-card tokens' lightness gap for a more pronounced machined look.

Gotchas — read before shipping

  • Test on the exact surface you ship. The same bloom that looks restrained on charcoal looks radioactive on true-black OLED.
  • Keep body copy near-white. Dark cards fail contrast fast, and --color-tpc08-mut here is the floor, not a starting point.
  • Large hover glows are cheap once and expensive twelve times. Reserve blooms for hero items.
  • color-mix() inside an arbitrary value must be typed closed-up with underscores for spaces — color-mix(in_oklch,…), never in oklch.
  • The accent is bright enough to need dark ink on the CTA (text-tpc08-onacc); white-on-cyan fails contrast.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

color-mix() needs Chrome 111+, Safari 16.2+, Firefox 113+ — and it is also Tailwind v4's own floor, so there is no version window where one works and the other does not.

Techniques used in this demo

Theme tokensset in @theme, used by a utility

HTML & JSno Tailwind involved

Search CodeFronts

Loading…