10 / 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 Material-Design Elevation Product Card
The Material recipe, and the port makes its central idea explicit: elevation is a named scale, so the two shadow tiers become --shadow-tpc10-e2 and --shadow-tpc10-e8 in @theme and the card reads shadow-tpc10-e2 group-hover:shadow-tpc10-e8. Key and ambient layers travel together as one token, exactly as the spec intends.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tpc-10 w-full min-h-svh grid place-items-center bg-tpc10-bg font-tpc10-sans px-5 py-14" aria-label="Material-design elevation product card demo">
<article class="group w-80 max-w-full rounded-xl overflow-hidden bg-tpc10-card shadow-tpc10-e2 transition-[translate,box-shadow] duration-300 ease-tpc10 hover:-translate-y-1.5 hover:shadow-tpc10-e8 focus-within:-translate-y-1.5 focus-within:shadow-tpc10-e8 motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div role="img" aria-label="Product photo: Terra ceramic planter" class="aspect-[16/10] bg-linear-[135deg,var(--color-tpc10-ph),var(--color-tpc10-ph2)] bg-[url('https://images.unsplash.com/photo-1485955900006-10f4d324d411?w=800&h=500&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="px-4.5 pt-4.5 pb-3.5">
<span class="inline-block px-3 py-1 rounded-full text-[11px] font-bold tracking-[0.06em] uppercase text-tpc10-acc bg-[color-mix(in_oklch,var(--color-tpc10-acc)_14%,oklch(1_0_0))]">Home</span>
<h3 class="mt-3 text-[19px] font-medium text-tpc10-ink text-pretty">Terra Ceramic Planter</h3>
<p class="mt-1 text-[13px] text-tpc10-mut">Matte glaze · 3 sizes</p>
<div class="mt-3.5 flex items-center justify-between gap-3">
<p class="text-[20px] font-bold text-tpc10-ink tabular-nums">$44</p>
<button type="button" class="relative overflow-hidden min-h-11 h-11 px-4 rounded-lg border-0 bg-transparent text-tpc10-acc text-[13px] font-bold tracking-[0.06em] uppercase cursor-pointer before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-200 before:ease-tpc10 hover:before:opacity-10 focus-visible:before:opacity-10 focus-visible:outline-2 focus-visible:outline-tpc10-acc focus-visible:outline-offset-2 motion-reduce:before:transition-none">Add to Cart</button>
</div>
</div>
</article>
</section><section class="tpc-10 w-full min-h-svh grid place-items-center bg-tpc10-bg font-tpc10-sans px-5 py-14" aria-label="Material-design elevation product card demo">
<article class="group w-80 max-w-full rounded-xl overflow-hidden bg-tpc10-card shadow-tpc10-e2 transition-[translate,box-shadow] duration-300 ease-tpc10 hover:-translate-y-1.5 hover:shadow-tpc10-e8 focus-within:-translate-y-1.5 focus-within:shadow-tpc10-e8 motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div role="img" aria-label="Product photo: Terra ceramic planter" class="aspect-[16/10] bg-linear-[135deg,var(--color-tpc10-ph),var(--color-tpc10-ph2)] bg-[url('https://images.unsplash.com/photo-1485955900006-10f4d324d411?w=800&h=500&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="px-4.5 pt-4.5 pb-3.5">
<span class="inline-block px-3 py-1 rounded-full text-[11px] font-bold tracking-[0.06em] uppercase text-tpc10-acc bg-[color-mix(in_oklch,var(--color-tpc10-acc)_14%,oklch(1_0_0))]">Home</span>
<h3 class="mt-3 text-[19px] font-medium text-tpc10-ink text-pretty">Terra Ceramic Planter</h3>
<p class="mt-1 text-[13px] text-tpc10-mut">Matte glaze · 3 sizes</p>
<div class="mt-3.5 flex items-center justify-between gap-3">
<p class="text-[20px] font-bold text-tpc10-ink tabular-nums">$44</p>
<button type="button" class="relative overflow-hidden min-h-11 h-11 px-4 rounded-lg border-0 bg-transparent text-tpc10-acc text-[13px] font-bold tracking-[0.06em] uppercase cursor-pointer before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-200 before:ease-tpc10 hover:before:opacity-10 focus-visible:before:opacity-10 focus-visible:outline-2 focus-visible:outline-tpc10-acc focus-visible:outline-offset-2 motion-reduce:before:transition-none">Add to Cart</button>
</div>
</div>
</article>
</section>@import "tailwindcss";
@theme {
--color-tpc10-bg: #eceff1;
--color-tpc10-bg: oklch(0.94 0.005 220);
--color-tpc10-card: #ffffff;
--color-tpc10-card: oklch(1 0 0);
--color-tpc10-ink: #1c2321;
--color-tpc10-ink: oklch(0.25 0.012 165);
--color-tpc10-mut: #5d6a65;
--color-tpc10-mut: oklch(0.5 0.012 165);
--color-tpc10-ph: #d7e3d9;
--color-tpc10-ph: oklch(0.9 0.02 155);
--color-tpc10-ph2: #c3d4c6;
--color-tpc10-ph2: oklch(0.84 0.028 155);
--color-tpc10-acc: #2e7d4f;
--color-tpc10-acc: oklch(0.52 0.13 150);
--font-tpc10-sans: 'Roboto', system-ui, sans-serif;
--font-tpc10-mono: 'Roboto Mono', ui-monospace, monospace;
/* The elevation scale as tokens: each tier is a key shadow plus an ambient
shadow, and the pair is one design decision — so it is one utility. */
--shadow-tpc10-e2: 0 2px 4px oklch(0 0 0 / 0.16), 0 8px 20px -8px oklch(0 0 0 / 0.22);
--shadow-tpc10-e8: 0 8px 12px oklch(0 0 0 / 0.2), 0 24px 44px -12px oklch(0 0 0 / 0.32);
--ease-tpc10: cubic-bezier(0.4, 0, 0.2, 1);
}
.tpc-10 {
width: 100%;
min-height: 100svh;
}
.tpc-10 ::selection {
background: var(--color-tpc10-acc);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tpc10-bg: #eceff1;
--color-tpc10-bg: oklch(0.94 0.005 220);
--color-tpc10-card: #ffffff;
--color-tpc10-card: oklch(1 0 0);
--color-tpc10-ink: #1c2321;
--color-tpc10-ink: oklch(0.25 0.012 165);
--color-tpc10-mut: #5d6a65;
--color-tpc10-mut: oklch(0.5 0.012 165);
--color-tpc10-ph: #d7e3d9;
--color-tpc10-ph: oklch(0.9 0.02 155);
--color-tpc10-ph2: #c3d4c6;
--color-tpc10-ph2: oklch(0.84 0.028 155);
--color-tpc10-acc: #2e7d4f;
--color-tpc10-acc: oklch(0.52 0.13 150);
--font-tpc10-sans: 'Roboto', system-ui, sans-serif;
--font-tpc10-mono: 'Roboto Mono', ui-monospace, monospace;
/* The elevation scale as tokens: each tier is a key shadow plus an ambient
shadow, and the pair is one design decision — so it is one utility. */
--shadow-tpc10-e2: 0 2px 4px oklch(0 0 0 / 0.16), 0 8px 20px -8px oklch(0 0 0 / 0.22);
--shadow-tpc10-e8: 0 8px 12px oklch(0 0 0 / 0.2), 0 24px 44px -12px oklch(0 0 0 / 0.32);
--ease-tpc10: cubic-bezier(0.4, 0, 0.2, 1);
}
.tpc-10 {
width: 100%;
min-height: 100svh;
}
.tpc-10 ::selection {
background: var(--color-tpc10-acc);
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-tpc10-bg: #eceff1;
--color-tpc10-bg: oklch(0.94 0.005 220);
--color-tpc10-card: #ffffff;
--color-tpc10-card: oklch(1 0 0);
--color-tpc10-ink: #1c2321;
--color-tpc10-ink: oklch(0.25 0.012 165);
--color-tpc10-mut: #5d6a65;
--color-tpc10-mut: oklch(0.5 0.012 165);
--color-tpc10-ph: #d7e3d9;
--color-tpc10-ph: oklch(0.9 0.02 155);
--color-tpc10-ph2: #c3d4c6;
--color-tpc10-ph2: oklch(0.84 0.028 155);
--color-tpc10-acc: #2e7d4f;
--color-tpc10-acc: oklch(0.52 0.13 150);
--font-tpc10-sans: 'Roboto', system-ui, sans-serif;
--font-tpc10-mono: 'Roboto Mono', ui-monospace, monospace;
/* The elevation scale as tokens: each tier is a key shadow plus an ambient
shadow, and the pair is one design decision — so it is one utility. */
--shadow-tpc10-e2: 0 2px 4px oklch(0 0 0 / 0.16), 0 8px 20px -8px oklch(0 0 0 / 0.22);
--shadow-tpc10-e8: 0 8px 12px oklch(0 0 0 / 0.2), 0 24px 44px -12px oklch(0 0 0 / 0.32);
--ease-tpc10: cubic-bezier(0.4, 0, 0.2, 1);
}
.tpc-10 {
width: 100%;
min-height: 100svh;
}
.tpc-10 ::selection {
background: var(--color-tpc10-acc);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tpc10-bg: #eceff1;
--color-tpc10-bg: oklch(0.94 0.005 220);
--color-tpc10-card: #ffffff;
--color-tpc10-card: oklch(1 0 0);
--color-tpc10-ink: #1c2321;
--color-tpc10-ink: oklch(0.25 0.012 165);
--color-tpc10-mut: #5d6a65;
--color-tpc10-mut: oklch(0.5 0.012 165);
--color-tpc10-ph: #d7e3d9;
--color-tpc10-ph: oklch(0.9 0.02 155);
--color-tpc10-ph2: #c3d4c6;
--color-tpc10-ph2: oklch(0.84 0.028 155);
--color-tpc10-acc: #2e7d4f;
--color-tpc10-acc: oklch(0.52 0.13 150);
--font-tpc10-sans: 'Roboto', system-ui, sans-serif;
--font-tpc10-mono: 'Roboto Mono', ui-monospace, monospace;
/* The elevation scale as tokens: each tier is a key shadow plus an ambient
shadow, and the pair is one design decision — so it is one utility. */
--shadow-tpc10-e2: 0 2px 4px oklch(0 0 0 / 0.16), 0 8px 20px -8px oklch(0 0 0 / 0.22);
--shadow-tpc10-e8: 0 8px 12px oklch(0 0 0 / 0.2), 0 24px 44px -12px oklch(0 0 0 / 0.32);
--ease-tpc10: cubic-bezier(0.4, 0, 0.2, 1);
}
.tpc-10 {
width: 100%;
min-height: 100svh;
}
.tpc-10 ::selection {
background: var(--color-tpc10-acc);
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=Roboto:wght@400;500;700&family=Roboto+Mono:wght@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=Roboto:wght@400;500;700&family=Roboto+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
--shadow-*entries in@themeare the right home for an elevation scale:shadow-tpc10-e2andshadow-tpc10-e8compose with every variant, and the key+ambient pair can never be half-changed.- The Material state overlay is one of the few places a
before:variant beats a real element — it is genuinely a paint layer over the button, andbefore:bg-currentinherits the button's own colour for free. --ease-tpc10holds Material's standard curve once. In the CSS version that cubic-bezier is typed out three times, which is three chances to mistype it.color-mix()stays an arbitrary value; a tonal container tint is computed from the accent, not a palette entry, and hard-coding the result would break the single-token retint.- Enhancement over the CSS original: the text button grew from 40px to
min-h-11(44px), gained afocus-visible:before:opacity-10twin for its hover overlay, and the card's lift now fires onfocus-withintoo.
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 Material-Design Elevation Product Card
Source: https://codefronts.com/components/tailwind-css-product-cards/tailwind-material-design-elevation-product-card/
The Material recipe, and the port makes its central idea explicit: elevation is a named scale, so the two shadow tiers become --shadow-tpc10-e2 and --shadow-tpc10-e8 in @theme and the card reads shadow-tpc10-e2 group-hover:shadow-tpc10-e8. Key and ambient layers travel together as one token, exactly as the spec intends.
## HTML
```html
<section class="tpc-10 w-full min-h-svh grid place-items-center bg-tpc10-bg font-tpc10-sans px-5 py-14" aria-label="Material-design elevation product card demo">
<article class="group w-80 max-w-full rounded-xl overflow-hidden bg-tpc10-card shadow-tpc10-e2 transition-[translate,box-shadow] duration-300 ease-tpc10 hover:-translate-y-1.5 hover:shadow-tpc10-e8 focus-within:-translate-y-1.5 focus-within:shadow-tpc10-e8 motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div role="img" aria-label="Product photo: Terra ceramic planter" class="aspect-[16/10] bg-linear-[135deg,var(--color-tpc10-ph),var(--color-tpc10-ph2)] bg-[url('https://images.unsplash.com/photo-1485955900006-10f4d324d411?w=800&h=500&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="px-4.5 pt-4.5 pb-3.5">
<span class="inline-block px-3 py-1 rounded-full text-[11px] font-bold tracking-[0.06em] uppercase text-tpc10-acc bg-[color-mix(in_oklch,var(--color-tpc10-acc)_14%,oklch(1_0_0))]">Home</span>
<h3 class="mt-3 text-[19px] font-medium text-tpc10-ink text-pretty">Terra Ceramic Planter</h3>
<p class="mt-1 text-[13px] text-tpc10-mut">Matte glaze · 3 sizes</p>
<div class="mt-3.5 flex items-center justify-between gap-3">
<p class="text-[20px] font-bold text-tpc10-ink tabular-nums">$44</p>
<button type="button" class="relative overflow-hidden min-h-11 h-11 px-4 rounded-lg border-0 bg-transparent text-tpc10-acc text-[13px] font-bold tracking-[0.06em] uppercase cursor-pointer before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-200 before:ease-tpc10 hover:before:opacity-10 focus-visible:before:opacity-10 focus-visible:outline-2 focus-visible:outline-tpc10-acc focus-visible:outline-offset-2 motion-reduce:before:transition-none">Add to Cart</button>
</div>
</div>
</article>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpc10-bg: #eceff1;
--color-tpc10-bg: oklch(0.94 0.005 220);
--color-tpc10-card: #ffffff;
--color-tpc10-card: oklch(1 0 0);
--color-tpc10-ink: #1c2321;
--color-tpc10-ink: oklch(0.25 0.012 165);
--color-tpc10-mut: #5d6a65;
--color-tpc10-mut: oklch(0.5 0.012 165);
--color-tpc10-ph: #d7e3d9;
--color-tpc10-ph: oklch(0.9 0.02 155);
--color-tpc10-ph2: #c3d4c6;
--color-tpc10-ph2: oklch(0.84 0.028 155);
--color-tpc10-acc: #2e7d4f;
--color-tpc10-acc: oklch(0.52 0.13 150);
--font-tpc10-sans: 'Roboto', system-ui, sans-serif;
--font-tpc10-mono: 'Roboto Mono', ui-monospace, monospace;
/* The elevation scale as tokens: each tier is a key shadow plus an ambient
shadow, and the pair is one design decision — so it is one utility. */
--shadow-tpc10-e2: 0 2px 4px oklch(0 0 0 / 0.16), 0 8px 20px -8px oklch(0 0 0 / 0.22);
--shadow-tpc10-e8: 0 8px 12px oklch(0 0 0 / 0.2), 0 24px 44px -12px oklch(0 0 0 / 0.32);
--ease-tpc10: cubic-bezier(0.4, 0, 0.2, 1);
}
.tpc-10 {
width: 100%;
min-height: 100svh;
}
.tpc-10 ::selection {
background: var(--color-tpc10-acc);
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 Material-Design Elevation Product Card
Source: https://codefronts.com/components/tailwind-css-product-cards/tailwind-material-design-elevation-product-card/
The Material recipe, and the port makes its central idea explicit: elevation is a named scale, so the two shadow tiers become --shadow-tpc10-e2 and --shadow-tpc10-e8 in @theme and the card reads shadow-tpc10-e2 group-hover:shadow-tpc10-e8. Key and ambient layers travel together as one token, exactly as the spec intends.
## HTML
```html
<section class="tpc-10 w-full min-h-svh grid place-items-center bg-tpc10-bg font-tpc10-sans px-5 py-14" aria-label="Material-design elevation product card demo">
<article class="group w-80 max-w-full rounded-xl overflow-hidden bg-tpc10-card shadow-tpc10-e2 transition-[translate,box-shadow] duration-300 ease-tpc10 hover:-translate-y-1.5 hover:shadow-tpc10-e8 focus-within:-translate-y-1.5 focus-within:shadow-tpc10-e8 motion-reduce:transition-none motion-reduce:hover:translate-y-0">
<div role="img" aria-label="Product photo: Terra ceramic planter" class="aspect-[16/10] bg-linear-[135deg,var(--color-tpc10-ph),var(--color-tpc10-ph2)] bg-[url('https://images.unsplash.com/photo-1485955900006-10f4d324d411?w=800&h=500&fit=crop&q=70')] bg-cover bg-center"></div>
<div class="px-4.5 pt-4.5 pb-3.5">
<span class="inline-block px-3 py-1 rounded-full text-[11px] font-bold tracking-[0.06em] uppercase text-tpc10-acc bg-[color-mix(in_oklch,var(--color-tpc10-acc)_14%,oklch(1_0_0))]">Home</span>
<h3 class="mt-3 text-[19px] font-medium text-tpc10-ink text-pretty">Terra Ceramic Planter</h3>
<p class="mt-1 text-[13px] text-tpc10-mut">Matte glaze · 3 sizes</p>
<div class="mt-3.5 flex items-center justify-between gap-3">
<p class="text-[20px] font-bold text-tpc10-ink tabular-nums">$44</p>
<button type="button" class="relative overflow-hidden min-h-11 h-11 px-4 rounded-lg border-0 bg-transparent text-tpc10-acc text-[13px] font-bold tracking-[0.06em] uppercase cursor-pointer before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-200 before:ease-tpc10 hover:before:opacity-10 focus-visible:before:opacity-10 focus-visible:outline-2 focus-visible:outline-tpc10-acc focus-visible:outline-offset-2 motion-reduce:before:transition-none">Add to Cart</button>
</div>
</div>
</article>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tpc10-bg: #eceff1;
--color-tpc10-bg: oklch(0.94 0.005 220);
--color-tpc10-card: #ffffff;
--color-tpc10-card: oklch(1 0 0);
--color-tpc10-ink: #1c2321;
--color-tpc10-ink: oklch(0.25 0.012 165);
--color-tpc10-mut: #5d6a65;
--color-tpc10-mut: oklch(0.5 0.012 165);
--color-tpc10-ph: #d7e3d9;
--color-tpc10-ph: oklch(0.9 0.02 155);
--color-tpc10-ph2: #c3d4c6;
--color-tpc10-ph2: oklch(0.84 0.028 155);
--color-tpc10-acc: #2e7d4f;
--color-tpc10-acc: oklch(0.52 0.13 150);
--font-tpc10-sans: 'Roboto', system-ui, sans-serif;
--font-tpc10-mono: 'Roboto Mono', ui-monospace, monospace;
/* The elevation scale as tokens: each tier is a key shadow plus an ambient
shadow, and the pair is one design decision — so it is one utility. */
--shadow-tpc10-e2: 0 2px 4px oklch(0 0 0 / 0.16), 0 8px 20px -8px oklch(0 0 0 / 0.22);
--shadow-tpc10-e8: 0 8px 12px oklch(0 0 0 / 0.2), 0 24px 44px -12px oklch(0 0 0 / 0.32);
--ease-tpc10: cubic-bezier(0.4, 0, 0.2, 1);
}
.tpc-10 {
width: 100%;
min-height: 100svh;
}
.tpc-10 ::selection {
background: var(--color-tpc10-acc);
color: #fff;
}
```How this works
Elevation as a token, not a shadow.
@theme {
--shadow-tpc10-e2: 0 2px 4px oklch(0 0 0/0.16), 0 8px 20px -8px oklch(0 0 0/0.22);
--shadow-tpc10-e8: 0 8px 12px oklch(0 0 0/0.2), 0 24px 44px -12px oklch(0 0 0/0.32);
}Each tier is a key shadow plus an ambient shadow, and the pair is inseparable — which is precisely why it belongs in one token rather than two utilities. The markup then says shadow-tpc10-e2 group-hover:shadow-tpc10-e8, which reads like the spec.
The state overlay is the one good pseudo-element. Material's flat text button darkens by drawing a low-opacity layer of its own colour over itself. That is genuinely a pseudo-element's job, and before: variants express it cleanly:
class="relative overflow-hidden before:absolute before:inset-0
before:bg-current before:opacity-0 before:transition-opacity
hover:before:opacity-10 focus-visible:before:opacity-10"One curve, everywhere. Material's standard easing is not decorative — using ease-tpc10 on the card, the chip and the overlay is what makes the card feel like one object.
Make it yours
- Add tiers:
--shadow-tpc10-e1/e4/e12in@theme, then compose them withfocus-within:andactive:for a full elevation ladder. - Accent:
--color-tpc10-accdrives the chip tint, the price, the text button and every focus ring. - Add a leading avatar/icon row above the media for the complete Material card header pattern.
- Swap the flat text button for a filled one —
bg-tpc10-acc text-white— if the CTA needs more weight. - Lift distance:
group-hover:-translate-y-1.5. Material depth is a hint; more than 8px reads as a jump.
Gotchas — read before shipping
- Use both shadow layers. A single shadow is the most common reason a 'Material' card looks flat and wrong.
- Animate
transformandbox-shadowonly. Faking the lift with margin reflows the whole grid. before:needsrelativeon the button andoverflow-hiddento respect the radius.- The chip's tonal fill must mix toward white, not toward transparent, or it darkens whatever sits behind the card.
- Keep the elevation change small. Material's own tiers are a few pixels apart, and exaggerating them is what makes ports look like parodies.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Layered box-shadow and transform lifts are universal; color-mix() for the chip tint needs Chrome 111+, Safari 16.2+, Firefox 113+ — the same floor as v4 itself.