06 / 18
All 18 in 18 Tailwind CSS Product Cards
- 01Tailwind Product Card with Hover-Reveal Add to Cart
- 02Pure-Tailwind 3D Flip Product Card with Spec Back
- 03Tailwind Contained Image Zoom Product Card
- 04Tailwind Mouse-Tracking 3D Tilt Product Card
- 05Tailwind Slide-Up Details Panel Product Card
- 06Tailwind Minimalist eCommerce Product Card
- 07Tailwind Glassmorphism Product Card
- 08Tailwind Dark-Mode Gadget Product Card with Accent Glow
- 09Tailwind Neon Glowing Conic-Border Product Card
- 10Tailwind Material-Design Elevation Product Card
- 11Tailwind Horizontal Product Card with Container Queries
- 12Tailwind Auto-Fit Product Catalog Grid
- 13Tailwind Sale Ribbon & Coupon Badge Product Card
- 14Tailwind Sneaker Card with Colourway & Size Picker
- 15Tailwind Digital Download Product Card
- 16Tailwind Food Delivery Card with Quantity Stepper
- 17Tailwind Real Estate Listing Card with Favourite Toggle
- 18Tailwind Subscription Pricing Card with Billing Switch
Tailwind Minimalist eCommerce Product Card
Restraint as the technique: no border, no shadow at rest, a Cormorant display name over a Jost micro-label, and a text CTA whose underline draws itself in from the left. The whole card is whitespace and type — and the one piece Tailwind has no utility for, the animated background-size underline, is a single arbitrary background value.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tpc-06 w-full min-h-svh grid place-items-center bg-tpc06-bg font-tpc06-sans px-5 py-14" aria-label="Minimalist eCommerce product card demo">
<article class="group w-80 max-w-full p-5 rounded-md bg-transparent transition-[background-color,box-shadow] duration-400 hover:bg-tpc06-card hover:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] focus-within:bg-tpc06-card focus-within:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] motion-reduce:transition-none">
<div role="img" aria-label="Product photo: fine gold hoop earrings" class="aspect-[4/5] bg-linear-[160deg,var(--color-tpc06-ph),var(--color-tpc06-ph2)] bg-[url('https://images.unsplash.com/photo-1535632066927-ab7c9ab60908?w=700&h=880&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="pt-5.5 px-1 pb-1.5 text-center">
<h3 class="font-tpc06-display text-[22px] font-normal tracking-[0.02em] text-tpc06-ink">Fine Gold Hoops</h3>
<p class="mt-2 text-[13px] font-light tracking-[0.12em] text-tpc06-mut tabular-nums">$320</p>
<a href="#fine-gold-hoops" class="inline-block mt-4.5 py-2 text-[11px] font-medium tracking-[0.22em] uppercase no-underline text-tpc06-ink bg-[linear-gradient(currentColor,currentColor)] bg-[position:0_100%] bg-[length:0_1px] bg-no-repeat transition-[background-size] duration-400 ease-out hover:bg-[length:100%_1px] focus-visible:bg-[length:100%_1px] focus-visible:outline-1 focus-visible:outline-dashed focus-visible:outline-tpc06-ink focus-visible:outline-offset-6 motion-reduce:transition-none">View product</a>
</div>
</article>
</section><section class="tpc-06 w-full min-h-svh grid place-items-center bg-tpc06-bg font-tpc06-sans px-5 py-14" aria-label="Minimalist eCommerce product card demo">
<article class="group w-80 max-w-full p-5 rounded-md bg-transparent transition-[background-color,box-shadow] duration-400 hover:bg-tpc06-card hover:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] focus-within:bg-tpc06-card focus-within:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] motion-reduce:transition-none">
<div role="img" aria-label="Product photo: fine gold hoop earrings" class="aspect-[4/5] bg-linear-[160deg,var(--color-tpc06-ph),var(--color-tpc06-ph2)] bg-[url('https://images.unsplash.com/photo-1535632066927-ab7c9ab60908?w=700&h=880&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="pt-5.5 px-1 pb-1.5 text-center">
<h3 class="font-tpc06-display text-[22px] font-normal tracking-[0.02em] text-tpc06-ink">Fine Gold Hoops</h3>
<p class="mt-2 text-[13px] font-light tracking-[0.12em] text-tpc06-mut tabular-nums">$320</p>
<a href="#fine-gold-hoops" class="inline-block mt-4.5 py-2 text-[11px] font-medium tracking-[0.22em] uppercase no-underline text-tpc06-ink bg-[linear-gradient(currentColor,currentColor)] bg-[position:0_100%] bg-[length:0_1px] bg-no-repeat transition-[background-size] duration-400 ease-out hover:bg-[length:100%_1px] focus-visible:bg-[length:100%_1px] focus-visible:outline-1 focus-visible:outline-dashed focus-visible:outline-tpc06-ink focus-visible:outline-offset-6 motion-reduce:transition-none">View product</a>
</div>
</article>
</section>@import "tailwindcss";
@theme {
--color-tpc06-bg: #faf9f6;
--color-tpc06-bg: oklch(0.98 0.005 85);
--color-tpc06-card: #ffffff;
--color-tpc06-card: oklch(1 0 0);
--color-tpc06-ink: #1a1a1a;
--color-tpc06-ink: oklch(0.22 0.002 85);
--color-tpc06-mut: #6e685e;
--color-tpc06-mut: oklch(0.5 0.012 85);
--color-tpc06-ph: #f0ece4;
--color-tpc06-ph: oklch(0.94 0.01 85);
--color-tpc06-ph2: #e6ded1;
--color-tpc06-ph2: oklch(0.9 0.015 85);
--font-tpc06-display: 'Cormorant Garamond', Georgia, serif;
--font-tpc06-sans: 'Jost', system-ui, sans-serif;
}
.tpc-06 {
width: 100%;
min-height: 100svh;
}
.tpc-06 ::selection {
background: var(--color-tpc06-ink);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tpc06-bg: #faf9f6;
--color-tpc06-bg: oklch(0.98 0.005 85);
--color-tpc06-card: #ffffff;
--color-tpc06-card: oklch(1 0 0);
--color-tpc06-ink: #1a1a1a;
--color-tpc06-ink: oklch(0.22 0.002 85);
--color-tpc06-mut: #6e685e;
--color-tpc06-mut: oklch(0.5 0.012 85);
--color-tpc06-ph: #f0ece4;
--color-tpc06-ph: oklch(0.94 0.01 85);
--color-tpc06-ph2: #e6ded1;
--color-tpc06-ph2: oklch(0.9 0.015 85);
--font-tpc06-display: 'Cormorant Garamond', Georgia, serif;
--font-tpc06-sans: 'Jost', system-ui, sans-serif;
}
.tpc-06 {
width: 100%;
min-height: 100svh;
}
.tpc-06 ::selection {
background: var(--color-tpc06-ink);
color: #fff;
}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-tpc06-bg: #faf9f6;
--color-tpc06-bg: oklch(0.98 0.005 85);
--color-tpc06-card: #ffffff;
--color-tpc06-card: oklch(1 0 0);
--color-tpc06-ink: #1a1a1a;
--color-tpc06-ink: oklch(0.22 0.002 85);
--color-tpc06-mut: #6e685e;
--color-tpc06-mut: oklch(0.5 0.012 85);
--color-tpc06-ph: #f0ece4;
--color-tpc06-ph: oklch(0.94 0.01 85);
--color-tpc06-ph2: #e6ded1;
--color-tpc06-ph2: oklch(0.9 0.015 85);
--font-tpc06-display: 'Cormorant Garamond', Georgia, serif;
--font-tpc06-sans: 'Jost', system-ui, sans-serif;
}
.tpc-06 {
width: 100%;
min-height: 100svh;
}
.tpc-06 ::selection {
background: var(--color-tpc06-ink);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tpc06-bg: #faf9f6;
--color-tpc06-bg: oklch(0.98 0.005 85);
--color-tpc06-card: #ffffff;
--color-tpc06-card: oklch(1 0 0);
--color-tpc06-ink: #1a1a1a;
--color-tpc06-ink: oklch(0.22 0.002 85);
--color-tpc06-mut: #6e685e;
--color-tpc06-mut: oklch(0.5 0.012 85);
--color-tpc06-ph: #f0ece4;
--color-tpc06-ph: oklch(0.94 0.01 85);
--color-tpc06-ph2: #e6ded1;
--color-tpc06-ph2: oklch(0.9 0.015 85);
--font-tpc06-display: 'Cormorant Garamond', Georgia, serif;
--font-tpc06-sans: 'Jost', system-ui, sans-serif;
}
.tpc-06 {
width: 100%;
min-height: 100svh;
}
.tpc-06 ::selection {
background: var(--color-tpc06-ink);
color: #fff;
}<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=Cormorant+Garamond:wght@400;500;600&family=Jost:wght@300;400;500&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=Cormorant+Garamond:wght@400;500;600&family=Jost:wght@300;400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The
backgroundshorthand in the CSS original (linear-gradient(...) 0 100%/0 1px no-repeat) splits into four explicit utilities. Longer, and strictly better: each axis of the trick is now separately editable and the animated one is named intransition-[background-size]. bg-[length:…]andbg-[position:…]show why v4's data-type hints exist —bg-[0_1px]alone cannot be disambiguated from a colour or an image.- The original's
--muted: #8a8378failed contrast on#faf9f6. Re-expressing it as an oklch token made the lightness explicit, and it moved tooklch(0.5 …)to clear 4.5:1. focus-visible:outline-dashedreplaces the original'soutline: 1px dotted— the same intent, but as a real utility with an offset token rather than a hand-written outline.- Enhancement over the CSS original: the card now also responds to
focus-within, so tabbing to the CTA materialises the same white card a mouse hover does, and the name moved to a display serif for a genuinely editorial read.
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 Minimalist eCommerce Product Card
Source: https://codefronts.com/components/tailwind-css-product-cards/tailwind-minimalist-ecommerce-product-card/
Restraint as the technique: no border, no shadow at rest, a Cormorant display name over a Jost micro-label, and a text CTA whose underline draws itself in from the left. The whole card is whitespace and type — and the one piece Tailwind has no utility for, the animated background-size underline, is a single arbitrary background value.
## HTML
```html
<section class="tpc-06 w-full min-h-svh grid place-items-center bg-tpc06-bg font-tpc06-sans px-5 py-14" aria-label="Minimalist eCommerce product card demo">
<article class="group w-80 max-w-full p-5 rounded-md bg-transparent transition-[background-color,box-shadow] duration-400 hover:bg-tpc06-card hover:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] focus-within:bg-tpc06-card focus-within:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] motion-reduce:transition-none">
<div role="img" aria-label="Product photo: fine gold hoop earrings" class="aspect-[4/5] bg-linear-[160deg,var(--color-tpc06-ph),var(--color-tpc06-ph2)] bg-[url('https://images.unsplash.com/photo-1535632066927-ab7c9ab60908?w=700&h=880&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="pt-5.5 px-1 pb-1.5 text-center">
<h3 class="font-tpc06-display text-[22px] font-normal tracking-[0.02em] text-tpc06-ink">Fine Gold Hoops</h3>
<p class="mt-2 text-[13px] font-light tracking-[0.12em] text-tpc06-mut tabular-nums">$320</p>
<a href="#fine-gold-hoops" class="inline-block mt-4.5 py-2 text-[11px] font-medium tracking-[0.22em] uppercase no-underline text-tpc06-ink bg-[linear-gradient(currentColor,currentColor)] bg-[position:0_100%] bg-[length:0_1px] bg-no-repeat transition-[background-size] duration-400 ease-out hover:bg-[length:100%_1px] focus-visible:bg-[length:100%_1px] focus-visible:outline-1 focus-visible:outline-dashed focus-visible:outline-tpc06-ink focus-visible:outline-offset-6 motion-reduce:transition-none">View product</a>
</div>
</article>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpc06-bg: #faf9f6;
--color-tpc06-bg: oklch(0.98 0.005 85);
--color-tpc06-card: #ffffff;
--color-tpc06-card: oklch(1 0 0);
--color-tpc06-ink: #1a1a1a;
--color-tpc06-ink: oklch(0.22 0.002 85);
--color-tpc06-mut: #6e685e;
--color-tpc06-mut: oklch(0.5 0.012 85);
--color-tpc06-ph: #f0ece4;
--color-tpc06-ph: oklch(0.94 0.01 85);
--color-tpc06-ph2: #e6ded1;
--color-tpc06-ph2: oklch(0.9 0.015 85);
--font-tpc06-display: 'Cormorant Garamond', Georgia, serif;
--font-tpc06-sans: 'Jost', system-ui, sans-serif;
}
.tpc-06 {
width: 100%;
min-height: 100svh;
}
.tpc-06 ::selection {
background: var(--color-tpc06-ink);
color: #fff;
}
```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 Minimalist eCommerce Product Card
Source: https://codefronts.com/components/tailwind-css-product-cards/tailwind-minimalist-ecommerce-product-card/
Restraint as the technique: no border, no shadow at rest, a Cormorant display name over a Jost micro-label, and a text CTA whose underline draws itself in from the left. The whole card is whitespace and type — and the one piece Tailwind has no utility for, the animated background-size underline, is a single arbitrary background value.
## HTML
```html
<section class="tpc-06 w-full min-h-svh grid place-items-center bg-tpc06-bg font-tpc06-sans px-5 py-14" aria-label="Minimalist eCommerce product card demo">
<article class="group w-80 max-w-full p-5 rounded-md bg-transparent transition-[background-color,box-shadow] duration-400 hover:bg-tpc06-card hover:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] focus-within:bg-tpc06-card focus-within:shadow-[0_24px_60px_-34px_oklch(0.2_0.01_80/0.28)] motion-reduce:transition-none">
<div role="img" aria-label="Product photo: fine gold hoop earrings" class="aspect-[4/5] bg-linear-[160deg,var(--color-tpc06-ph),var(--color-tpc06-ph2)] bg-[url('https://images.unsplash.com/photo-1535632066927-ab7c9ab60908?w=700&h=880&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="pt-5.5 px-1 pb-1.5 text-center">
<h3 class="font-tpc06-display text-[22px] font-normal tracking-[0.02em] text-tpc06-ink">Fine Gold Hoops</h3>
<p class="mt-2 text-[13px] font-light tracking-[0.12em] text-tpc06-mut tabular-nums">$320</p>
<a href="#fine-gold-hoops" class="inline-block mt-4.5 py-2 text-[11px] font-medium tracking-[0.22em] uppercase no-underline text-tpc06-ink bg-[linear-gradient(currentColor,currentColor)] bg-[position:0_100%] bg-[length:0_1px] bg-no-repeat transition-[background-size] duration-400 ease-out hover:bg-[length:100%_1px] focus-visible:bg-[length:100%_1px] focus-visible:outline-1 focus-visible:outline-dashed focus-visible:outline-tpc06-ink focus-visible:outline-offset-6 motion-reduce:transition-none">View product</a>
</div>
</article>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpc06-bg: #faf9f6;
--color-tpc06-bg: oklch(0.98 0.005 85);
--color-tpc06-card: #ffffff;
--color-tpc06-card: oklch(1 0 0);
--color-tpc06-ink: #1a1a1a;
--color-tpc06-ink: oklch(0.22 0.002 85);
--color-tpc06-mut: #6e685e;
--color-tpc06-mut: oklch(0.5 0.012 85);
--color-tpc06-ph: #f0ece4;
--color-tpc06-ph: oklch(0.94 0.01 85);
--color-tpc06-ph2: #e6ded1;
--color-tpc06-ph2: oklch(0.9 0.015 85);
--font-tpc06-display: 'Cormorant Garamond', Georgia, serif;
--font-tpc06-sans: 'Jost', system-ui, sans-serif;
}
.tpc-06 {
width: 100%;
min-height: 100svh;
}
.tpc-06 ::selection {
background: var(--color-tpc06-ink);
color: #fff;
}
```How this works
The underline is a background, not a border. A border cannot animate its width from the left; a background gradient can, because background-size is animatable:
<a class="bg-[linear-gradient(currentColor,currentColor)]
bg-[position:0_100%] bg-[length:0_1px] bg-no-repeat
transition-[background-size] duration-400
hover:bg-[length:100%_1px] focus-visible:bg-[length:100%_1px]">currentColor means the rule never needs a colour of its own — retint the text and the underline follows.
Hierarchy without weight. The product name is 400-weight at 20px in a display serif; the price is 300-weight and smaller; the CTA is 11px with enormous tracking. Nothing is bold, and the reading order is still unambiguous — which is the actual skill this pattern is teaching.
The card appears on hover. At rest there is no card: transparent background, no shadow, no border. group-hover: fades in a white fill and a very wide, very faint shadow, so the object materialises under the cursor instead of lifting.
Make it yours
- Whitespace is the dial: the media's
aspect-[4/5]and the body'spt-5.5. More space reads more expensive. - Keep weights at 300–500 and let
tracking-*carry the tone. A bold weight anywhere breaks the effect. - Swap the underline for a sliding arrow: replace the background utilities with an inline
→span andgroup-hover:translate-x-1. - Palette:
--color-tpc06-inkand--color-tpc06-mutonly. Saturated accents are what makes minimalist cards look cheap. - Centre or left-align the body block — centred reads editorial, left-aligned reads catalog.
Gotchas — read before shipping
- Minimal still needs contrast.
--color-tpc06-mutis tuned to stay above 4.5:1 on the warm off-white; lightening it further fails WCAG. - A text CTA must still be a real
<a>or<button>with a visible focus state — underlined text with no focus style is a keyboard dead end. bg-[length:…]andbg-[position:…]need the explicit data-type prefix. Barebg-[0_1px]is ambiguous and compiles to nothing.- Resist adding badges, shadows and borders 'to help'. The value of this card is entirely what is left out.
- Don't transition
allhere: the link has a gradient background, and transitioning it repaints the gradient on every frame.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Animated background-size underlines and subtle shadows are universally supported; the floor is Tailwind v4's generated sheet.