19 / 20
All 20 in 20 Tailwind CSS Image Hover Effects
- 01Tailwind Image Hover Zoom In Card
- 02Tailwind Hover Reveal Text Over Image
- 03Tailwind E-Commerce Product Image Swap on Hover
- 04Tailwind Grid Image Blur Overlay Text Hover
- 05Tailwind Card Slide Up Caption on Hover
- 06Tailwind Grayscale to Color Image Hover
- 07Tailwind Image Color Overlay Tint on Hover
- 08Tailwind Neumorphic Image Card Hover Effect
- 09Tailwind Glassmorphism Overlay on Image Hover
- 10Tailwind Glowing Neon Border Image Hover
- 11Tailwind Image Clip-Path Transition Hover
- 12Tailwind Image Tilt 3D Perspective Hover
- 13Tailwind Shining Light Glare Image Hover
- 14Tailwind Image Split Transition Hover
- 15Tailwind Image Ripple Animation Hover
- 16Tailwind Circular Team Profile Avatar Hover
- 17Tailwind Fullscreen Background Image Hover
- 18Tailwind Masonry Gallery Zoom Hover
- 19Tailwind Image Icon Reveal Center Hover
- 20Tailwind Image Card Flip 3D Animation Hover
Tailwind Image Icon Reveal Center Hover
The artwork darkens and an action button pops in at the centre, spinning up from scale-50 -rotate-20 to rest. In v4 those are two individual properties, which quietly removes the CSS version's biggest footgun: transform function order no longer matters, because there is no shorthand to order.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tih-19 w-full min-h-svh grid place-items-center bg-tih19-bg font-tih19-sans px-6 py-10" aria-label="Centre icon reveal hover demo">
<div class="grid w-full max-w-195 gap-3 grid-cols-2 sm:grid-cols-3">
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-reel/800/600'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.31_0.14_280),oklch(0.45_0.19_275))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Intro Reel 2026">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Intro Reel 2026</span>
<span class="text-[10px] text-tih19-muted tabular-nums">4.2k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-jungle/800/600'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Jungle Macro">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Jungle Macro</span>
<span class="text-[10px] text-tih19-muted tabular-nums">1.8k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-prism/800/600'),linear-gradient(135deg,oklch(0.25_0.13_305),oklch(0.45_0.22_300),oklch(0.63_0.21_300))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Prism Study">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Prism Study</span>
<span class="text-[10px] text-tih19-muted tabular-nums">9.1k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-golden/800/600'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.45_0.11_60),oklch(0.65_0.14_65))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Golden Hour BTS">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Golden Hour BTS</span>
<span class="text-[10px] text-tih19-muted tabular-nums">3.3k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-blue/800/600'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.55_0.2_260))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Deep Blue Series">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Deep Blue Series</span>
<span class="text-[10px] text-tih19-muted tabular-nums">7.6k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-bloom/800/600'),linear-gradient(135deg,oklch(0.16_0.06_350),oklch(0.4_0.18_5),oklch(0.6_0.22_15))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Bloom Editorial">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Bloom Editorial</span>
<span class="text-[10px] text-tih19-muted tabular-nums">2.9k views</span>
</div>
</article>
</div>
</section><section class="tih-19 w-full min-h-svh grid place-items-center bg-tih19-bg font-tih19-sans px-6 py-10" aria-label="Centre icon reveal hover demo">
<div class="grid w-full max-w-195 gap-3 grid-cols-2 sm:grid-cols-3">
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-reel/800/600'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.31_0.14_280),oklch(0.45_0.19_275))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Intro Reel 2026">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Intro Reel 2026</span>
<span class="text-[10px] text-tih19-muted tabular-nums">4.2k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-jungle/800/600'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Jungle Macro">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Jungle Macro</span>
<span class="text-[10px] text-tih19-muted tabular-nums">1.8k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-prism/800/600'),linear-gradient(135deg,oklch(0.25_0.13_305),oklch(0.45_0.22_300),oklch(0.63_0.21_300))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Prism Study">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Prism Study</span>
<span class="text-[10px] text-tih19-muted tabular-nums">9.1k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-golden/800/600'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.45_0.11_60),oklch(0.65_0.14_65))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Golden Hour BTS">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Golden Hour BTS</span>
<span class="text-[10px] text-tih19-muted tabular-nums">3.3k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-blue/800/600'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.55_0.2_260))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Deep Blue Series">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Deep Blue Series</span>
<span class="text-[10px] text-tih19-muted tabular-nums">7.6k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-bloom/800/600'),linear-gradient(135deg,oklch(0.16_0.06_350),oklch(0.4_0.18_5),oklch(0.6_0.22_15))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Bloom Editorial">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Bloom Editorial</span>
<span class="text-[10px] text-tih19-muted tabular-nums">2.9k views</span>
</div>
</article>
</div>
</section>@import "tailwindcss";
@theme {
--color-tih19-bg: #07070e;
--color-tih19-bg: oklch(0.11 0.012 285);
--color-tih19-text: #f1f5f9;
--color-tih19-text: oklch(0.96 0.005 250);
--color-tih19-muted: #475569;
--color-tih19-muted: oklch(0.68 0.02 255);
--color-tih19-acc: #818cf8;
--color-tih19-acc: oklch(0.7 0.15 275);
--font-tih19-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih19: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-19 {
width: 100%;
min-height: 100svh;
}
.tih-19 ::selection {
background: oklch(0.7 0.15 275);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tih19-bg: #07070e;
--color-tih19-bg: oklch(0.11 0.012 285);
--color-tih19-text: #f1f5f9;
--color-tih19-text: oklch(0.96 0.005 250);
--color-tih19-muted: #475569;
--color-tih19-muted: oklch(0.68 0.02 255);
--color-tih19-acc: #818cf8;
--color-tih19-acc: oklch(0.7 0.15 275);
--font-tih19-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih19: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-19 {
width: 100%;
min-height: 100svh;
}
.tih-19 ::selection {
background: oklch(0.7 0.15 275);
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-tih19-bg: #07070e;
--color-tih19-bg: oklch(0.11 0.012 285);
--color-tih19-text: #f1f5f9;
--color-tih19-text: oklch(0.96 0.005 250);
--color-tih19-muted: #475569;
--color-tih19-muted: oklch(0.68 0.02 255);
--color-tih19-acc: #818cf8;
--color-tih19-acc: oklch(0.7 0.15 275);
--font-tih19-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih19: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-19 {
width: 100%;
min-height: 100svh;
}
.tih-19 ::selection {
background: oklch(0.7 0.15 275);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tih19-bg: #07070e;
--color-tih19-bg: oklch(0.11 0.012 285);
--color-tih19-text: #f1f5f9;
--color-tih19-text: oklch(0.96 0.005 250);
--color-tih19-muted: #475569;
--color-tih19-muted: oklch(0.68 0.02 255);
--color-tih19-acc: #818cf8;
--color-tih19-acc: oklch(0.7 0.15 275);
--font-tih19-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih19: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-19 {
width: 100%;
min-height: 100svh;
}
.tih-19 ::selection {
background: oklch(0.7 0.15 275);
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=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;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=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.
- The CSS version's ordering gotcha (
scale() rotate()vsrotate() scale()) simply does not exist in the port:scale-50and-rotate-20set separate properties with a specified application order. filter: brightness(0.4)becomesgroup-hover:brightness-40, composable with the neighbouringscalein onetransition-[filter,scale].- The icon div became a real
<button>with anaria-labelper card, plusfocus-within:on its wrapper so the pop happens on focus too — the original reveals an unreachable control. - Two hover scopes coexist on one card:
group-hover:for the reveal and the button's ownhover:scale-110. The CSS version needs the.card:hover .btn:hovercompound selector to express it. tabular-numson the view counts stops the strip twitching between cards of different digit widths.- The stylesheet is again just tokens, the root rule and
::selection. Nothing in this demo needed CSS.
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 Image Icon Reveal Center Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-image-icon-reveal-center-hover/
The artwork darkens and an action button pops in at the centre, spinning up from scale-50 -rotate-20 to rest. In v4 those are two individual properties, which quietly removes the CSS version's biggest footgun: transform function order no longer matters, because there is no shorthand to order.
## HTML
```html
<section class="tih-19 w-full min-h-svh grid place-items-center bg-tih19-bg font-tih19-sans px-6 py-10" aria-label="Centre icon reveal hover demo">
<div class="grid w-full max-w-195 gap-3 grid-cols-2 sm:grid-cols-3">
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-reel/800/600'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.31_0.14_280),oklch(0.45_0.19_275))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Intro Reel 2026">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Intro Reel 2026</span>
<span class="text-[10px] text-tih19-muted tabular-nums">4.2k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-jungle/800/600'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Jungle Macro">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Jungle Macro</span>
<span class="text-[10px] text-tih19-muted tabular-nums">1.8k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-prism/800/600'),linear-gradient(135deg,oklch(0.25_0.13_305),oklch(0.45_0.22_300),oklch(0.63_0.21_300))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Prism Study">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Prism Study</span>
<span class="text-[10px] text-tih19-muted tabular-nums">9.1k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-golden/800/600'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.45_0.11_60),oklch(0.65_0.14_65))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Golden Hour BTS">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Golden Hour BTS</span>
<span class="text-[10px] text-tih19-muted tabular-nums">3.3k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-blue/800/600'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.55_0.2_260))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Deep Blue Series">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Deep Blue Series</span>
<span class="text-[10px] text-tih19-muted tabular-nums">7.6k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-bloom/800/600'),linear-gradient(135deg,oklch(0.16_0.06_350),oklch(0.4_0.18_5),oklch(0.6_0.22_15))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Bloom Editorial">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Bloom Editorial</span>
<span class="text-[10px] text-tih19-muted tabular-nums">2.9k views</span>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih19-bg: #07070e;
--color-tih19-bg: oklch(0.11 0.012 285);
--color-tih19-text: #f1f5f9;
--color-tih19-text: oklch(0.96 0.005 250);
--color-tih19-muted: #475569;
--color-tih19-muted: oklch(0.68 0.02 255);
--color-tih19-acc: #818cf8;
--color-tih19-acc: oklch(0.7 0.15 275);
--font-tih19-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih19: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-19 {
width: 100%;
min-height: 100svh;
}
.tih-19 ::selection {
background: oklch(0.7 0.15 275);
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 Image Icon Reveal Center Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-image-icon-reveal-center-hover/
The artwork darkens and an action button pops in at the centre, spinning up from scale-50 -rotate-20 to rest. In v4 those are two individual properties, which quietly removes the CSS version's biggest footgun: transform function order no longer matters, because there is no shorthand to order.
## HTML
```html
<section class="tih-19 w-full min-h-svh grid place-items-center bg-tih19-bg font-tih19-sans px-6 py-10" aria-label="Centre icon reveal hover demo">
<div class="grid w-full max-w-195 gap-3 grid-cols-2 sm:grid-cols-3">
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-reel/800/600'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.31_0.14_280),oklch(0.45_0.19_275))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Intro Reel 2026">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Intro Reel 2026</span>
<span class="text-[10px] text-tih19-muted tabular-nums">4.2k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-jungle/800/600'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Jungle Macro">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Jungle Macro</span>
<span class="text-[10px] text-tih19-muted tabular-nums">1.8k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-prism/800/600'),linear-gradient(135deg,oklch(0.25_0.13_305),oklch(0.45_0.22_300),oklch(0.63_0.21_300))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Prism Study">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Prism Study</span>
<span class="text-[10px] text-tih19-muted tabular-nums">9.1k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-golden/800/600'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.45_0.11_60),oklch(0.65_0.14_65))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Play Golden Hour BTS">▶</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Golden Hour BTS</span>
<span class="text-[10px] text-tih19-muted tabular-nums">3.3k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-blue/800/600'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.55_0.2_260))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Zoom Deep Blue Series">🔍</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Deep Blue Series</span>
<span class="text-[10px] text-tih19-muted tabular-nums">7.6k views</span>
</div>
</article>
<article class="group relative overflow-hidden rounded-[10px] aspect-[4/3]">
<div class="absolute inset-0 bg-[image:url('https://picsum.photos/seed/tih19-bloom/800/600'),linear-gradient(135deg,oklch(0.16_0.06_350),oklch(0.4_0.18_5),oklch(0.6_0.22_15))] bg-cover bg-center bg-no-repeat transition-[filter,scale] duration-380 ease-tih19 group-hover:brightness-40 group-hover:scale-106 motion-reduce:transition-none motion-reduce:group-hover:scale-100"></div>
<div class="absolute inset-0 grid place-items-center opacity-0 scale-50 -rotate-20 transition-[opacity,scale,rotate] duration-380 ease-tih19 group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0 focus-within:opacity-100 focus-within:scale-100 focus-within:rotate-0 motion-reduce:transition-none motion-reduce:opacity-100 motion-reduce:scale-100 motion-reduce:rotate-0">
<button type="button" class="grid place-items-center w-13 h-13 rounded-full text-[22px] text-white bg-[oklch(1_0_0/0.12)] border-2 border-[oklch(1_0_0/0.25)] backdrop-blur-md cursor-pointer transition-[background,scale] duration-200 hover:bg-[oklch(1_0_0/0.22)] hover:scale-110 focus-visible:outline-2 focus-visible:outline-tih19-acc focus-visible:outline-offset-2 motion-reduce:transition-none" aria-label="Open Bloom Editorial">🔗</button>
</div>
<div class="absolute inset-x-0 bottom-0 flex items-center justify-between px-2.5 py-2 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
<span class="text-[11px] font-bold text-tih19-text">Bloom Editorial</span>
<span class="text-[10px] text-tih19-muted tabular-nums">2.9k views</span>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih19-bg: #07070e;
--color-tih19-bg: oklch(0.11 0.012 285);
--color-tih19-text: #f1f5f9;
--color-tih19-text: oklch(0.96 0.005 250);
--color-tih19-muted: #475569;
--color-tih19-muted: oklch(0.68 0.02 255);
--color-tih19-acc: #818cf8;
--color-tih19-acc: oklch(0.7 0.15 275);
--font-tih19-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih19: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-19 {
width: 100%;
min-height: 100svh;
}
.tih-19 ::selection {
background: oklch(0.7 0.15 275);
color: #fff;
}
```How this works
Individual transform properties end the ordering trap. The CSS version warns that scale(0.5) rotate(-20deg) is not the same as rotate(-20deg) scale(0.5). v4 compiles scale-50 and -rotate-20 to the separate scale and rotate properties, which the browser applies in a fixed, specified order — so the two utilities commute and one can be overridden without touching the other.
class="opacity-0 scale-50 -rotate-20
transition-[opacity,scale,rotate] duration-380 ease-tih19
group-hover:opacity-100 group-hover:scale-100 group-hover:rotate-0"Centring needs no offsets. absolute inset-0 grid place-items-center centres the button in the card with no translate maths, which also means the scale animates from the true centre.
Two hover scopes. The card's hover brings the button in; the button's own hover:scale-110 adds the second micro-interaction. Utilities keep the two scopes visibly distinct.
Make it yours
- Per-card icon: the glyph inside the button. Everything else is shared.
- Soft-focus variant:
group-hover:blur-[2px] group-hover:brightness-70on the artwork. - Tooltip: a sibling label with
group-hover:opacity-100 group-hover:delay-100. - Pop character:
ease-[cubic-bezier(0.34,1.8,0.64,1)]for more overshoot. - Swap emoji for inline SVG with
fill-current— sharper at every DPI and colour-controlled by one utility.
Gotchas — read before shipping
- A
filteron the artwork creates a stacking context; keepfixeddescendants out of filtered cards or they will be clipped. - Spring easing on a scale can overshoot past the card edge; the frame's
overflow-hiddenis what keeps that tidy. - Negative rotation is
-rotate-20(leading minus on the utility), while negative arbitrary values go inside brackets. Both forms exist and they are not interchangeable. - The button is a real
<button>with a label, not a styled div — a hover-revealed control still has to be reachable and announced. transition-[opacity,scale,rotate], nottransition-transform: namingtransformanimates nothing when the utilities set individual properties.- The browser CDN build compiles in the page and is for prototyping only. Ship the CLI or a plugin build.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Individual scale/rotate properties are Baseline 2022 — the same floor as v4's transform utilities.