11 / 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 Clip-Path Transition Hover
Shape morphing where both shapes sit on the same element as two arbitrary clip-path utilities — resting and hovered, one line apart. Since interpolation requires matching vertex counts, having both values visible together is not cosmetic: it is what stops the pair from silently degrading into a hard cut.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tih-11 w-full min-h-svh grid place-items-center bg-tih11-bg font-tih11-sans px-6 py-10" aria-label="Clip-path shape morph hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-moon/600/600'),radial-gradient(circle,oklch(0.28_0.11_290),oklch(0.35_0.18_295),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat [clip-path:circle(42%_at_50%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:polygon(10%_0%,90%_0%,100%_10%,100%_90%,90%_100%,10%_100%,0%_90%,0%_10%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:circle(42%_at_50%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Circle<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Rounded Rect</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Orbital Shift</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-gem/600/600'),radial-gradient(circle,oklch(0.25_0.05_180),oklch(0.42_0.09_165),oklch(0.8_0.14_163))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:circle(48%_at_50%_50%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Diamond<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Circle</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Gem Reveal</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-lattice/600/600'),radial-gradient(circle,oklch(0.2_0.02_60),oklch(0.45_0.11_60),oklch(0.78_0.16_72))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] transition-[clip-path,scale,rotate] duration-500 ease-tih11 group-hover:[clip-path:polygon(25%_0%,75%_0%,100%_50%,75%_100%,25%_100%,0%_50%)] group-hover:scale-105 group-hover:rotate-30 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] motion-reduce:group-hover:scale-100 motion-reduce:group-hover:rotate-0">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Hex<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Wide Hex + Spin</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Lattice Morph</p>
</div>
</article>
</div>
</section><section class="tih-11 w-full min-h-svh grid place-items-center bg-tih11-bg font-tih11-sans px-6 py-10" aria-label="Clip-path shape morph hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-moon/600/600'),radial-gradient(circle,oklch(0.28_0.11_290),oklch(0.35_0.18_295),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat [clip-path:circle(42%_at_50%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:polygon(10%_0%,90%_0%,100%_10%,100%_90%,90%_100%,10%_100%,0%_90%,0%_10%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:circle(42%_at_50%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Circle<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Rounded Rect</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Orbital Shift</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-gem/600/600'),radial-gradient(circle,oklch(0.25_0.05_180),oklch(0.42_0.09_165),oklch(0.8_0.14_163))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:circle(48%_at_50%_50%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Diamond<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Circle</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Gem Reveal</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-lattice/600/600'),radial-gradient(circle,oklch(0.2_0.02_60),oklch(0.45_0.11_60),oklch(0.78_0.16_72))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] transition-[clip-path,scale,rotate] duration-500 ease-tih11 group-hover:[clip-path:polygon(25%_0%,75%_0%,100%_50%,75%_100%,25%_100%,0%_50%)] group-hover:scale-105 group-hover:rotate-30 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] motion-reduce:group-hover:scale-100 motion-reduce:group-hover:rotate-0">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Hex<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Wide Hex + Spin</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Lattice Morph</p>
</div>
</article>
</div>
</section>@import "tailwindcss";
@theme {
--color-tih11-bg: #08080d;
--color-tih11-bg: oklch(0.12 0.008 285);
--color-tih11-text: #f1f5f9;
--color-tih11-text: oklch(0.96 0.005 250);
--color-tih11-muted: #64748b;
--color-tih11-muted: oklch(0.58 0.035 255);
--color-tih11-acc: #e879f9;
--color-tih11-acc: oklch(0.78 0.19 320);
--font-tih11-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih11: cubic-bezier(0.34, 1.56, 0.64, 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-11 {
width: 100%;
min-height: 100svh;
}
.tih-11 ::selection {
background: oklch(0.78 0.19 320);
color: #000;
}@import "tailwindcss";
@theme {
--color-tih11-bg: #08080d;
--color-tih11-bg: oklch(0.12 0.008 285);
--color-tih11-text: #f1f5f9;
--color-tih11-text: oklch(0.96 0.005 250);
--color-tih11-muted: #64748b;
--color-tih11-muted: oklch(0.58 0.035 255);
--color-tih11-acc: #e879f9;
--color-tih11-acc: oklch(0.78 0.19 320);
--font-tih11-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih11: cubic-bezier(0.34, 1.56, 0.64, 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-11 {
width: 100%;
min-height: 100svh;
}
.tih-11 ::selection {
background: oklch(0.78 0.19 320);
color: #000;
}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-tih11-bg: #08080d;
--color-tih11-bg: oklch(0.12 0.008 285);
--color-tih11-text: #f1f5f9;
--color-tih11-text: oklch(0.96 0.005 250);
--color-tih11-muted: #64748b;
--color-tih11-muted: oklch(0.58 0.035 255);
--color-tih11-acc: #e879f9;
--color-tih11-acc: oklch(0.78 0.19 320);
--font-tih11-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih11: cubic-bezier(0.34, 1.56, 0.64, 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-11 {
width: 100%;
min-height: 100svh;
}
.tih-11 ::selection {
background: oklch(0.78 0.19 320);
color: #000;
}@import "tailwindcss";
@theme {
--color-tih11-bg: #08080d;
--color-tih11-bg: oklch(0.12 0.008 285);
--color-tih11-text: #f1f5f9;
--color-tih11-text: oklch(0.96 0.005 250);
--color-tih11-muted: #64748b;
--color-tih11-muted: oklch(0.58 0.035 255);
--color-tih11-acc: #e879f9;
--color-tih11-acc: oklch(0.78 0.19 320);
--font-tih11-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih11: cubic-bezier(0.34, 1.56, 0.64, 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-11 {
width: 100%;
min-height: 100svh;
}
.tih-11 ::selection {
background: oklch(0.78 0.19 320);
color: #000;
}<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.
- Six rules (three resting shapes, three hover shapes) become three elements carrying both of their own shapes. For a pattern whose main failure is mismatched vertex counts, adjacency is the feature.
transform: scale(1.05) rotate(30deg)becomesgroup-hover:scale-105 group-hover:rotate-30— two individual properties, independently overridable, which the shorthand cannot do.transition-[clip-path,scale,rotate]names the individual properties rather thantransform, because that is what v4's utilities actually set.- The spring easing stays a single
@themeentry shared by all three cards, so the overshoot cannot drift between them. motion-reduce:group-hover:[clip-path:…]repeats the resting shape to cancel the morph. Verbose, and still better than a media-query block restating three selectors.- Nothing but the root rule and
::selectionremains in CSS — even the radial-gradient fills became utilities.
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 Clip-Path Transition Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-image-clip-path-transition-hover/
Shape morphing where both shapes sit on the same element as two arbitrary clip-path utilities — resting and hovered, one line apart. Since interpolation requires matching vertex counts, having both values visible together is not cosmetic: it is what stops the pair from silently degrading into a hard cut.
## HTML
```html
<section class="tih-11 w-full min-h-svh grid place-items-center bg-tih11-bg font-tih11-sans px-6 py-10" aria-label="Clip-path shape morph hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-moon/600/600'),radial-gradient(circle,oklch(0.28_0.11_290),oklch(0.35_0.18_295),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat [clip-path:circle(42%_at_50%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:polygon(10%_0%,90%_0%,100%_10%,100%_90%,90%_100%,10%_100%,0%_90%,0%_10%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:circle(42%_at_50%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Circle<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Rounded Rect</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Orbital Shift</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-gem/600/600'),radial-gradient(circle,oklch(0.25_0.05_180),oklch(0.42_0.09_165),oklch(0.8_0.14_163))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:circle(48%_at_50%_50%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Diamond<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Circle</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Gem Reveal</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-lattice/600/600'),radial-gradient(circle,oklch(0.2_0.02_60),oklch(0.45_0.11_60),oklch(0.78_0.16_72))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] transition-[clip-path,scale,rotate] duration-500 ease-tih11 group-hover:[clip-path:polygon(25%_0%,75%_0%,100%_50%,75%_100%,25%_100%,0%_50%)] group-hover:scale-105 group-hover:rotate-30 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] motion-reduce:group-hover:scale-100 motion-reduce:group-hover:rotate-0">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Hex<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Wide Hex + Spin</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Lattice Morph</p>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih11-bg: #08080d;
--color-tih11-bg: oklch(0.12 0.008 285);
--color-tih11-text: #f1f5f9;
--color-tih11-text: oklch(0.96 0.005 250);
--color-tih11-muted: #64748b;
--color-tih11-muted: oklch(0.58 0.035 255);
--color-tih11-acc: #e879f9;
--color-tih11-acc: oklch(0.78 0.19 320);
--font-tih11-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih11: cubic-bezier(0.34, 1.56, 0.64, 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-11 {
width: 100%;
min-height: 100svh;
}
.tih-11 ::selection {
background: oklch(0.78 0.19 320);
color: #000;
}
```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 Clip-Path Transition Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-image-clip-path-transition-hover/
Shape morphing where both shapes sit on the same element as two arbitrary clip-path utilities — resting and hovered, one line apart. Since interpolation requires matching vertex counts, having both values visible together is not cosmetic: it is what stops the pair from silently degrading into a hard cut.
## HTML
```html
<section class="tih-11 w-full min-h-svh grid place-items-center bg-tih11-bg font-tih11-sans px-6 py-10" aria-label="Clip-path shape morph hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-moon/600/600'),radial-gradient(circle,oklch(0.28_0.11_290),oklch(0.35_0.18_295),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat [clip-path:circle(42%_at_50%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:polygon(10%_0%,90%_0%,100%_10%,100%_90%,90%_100%,10%_100%,0%_90%,0%_10%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:circle(42%_at_50%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Circle<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Rounded Rect</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Orbital Shift</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-gem/600/600'),radial-gradient(circle,oklch(0.25_0.05_180),oklch(0.42_0.09_165),oklch(0.8_0.14_163))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] transition-[clip-path,scale] duration-500 ease-tih11 group-hover:[clip-path:circle(48%_at_50%_50%)] group-hover:scale-105 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_50%,50%_100%,0%_50%)] motion-reduce:group-hover:scale-100">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Diamond<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Circle</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Gem Reveal</p>
</div>
</article>
<article class="group flex flex-col items-center gap-3">
<div class="relative w-full aspect-square overflow-visible">
<div class="grid place-items-center w-full h-full bg-[image:url('https://picsum.photos/seed/tih11-lattice/600/600'),radial-gradient(circle,oklch(0.2_0.02_60),oklch(0.45_0.11_60),oklch(0.78_0.16_72))] bg-cover bg-center bg-no-repeat [clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] transition-[clip-path,scale,rotate] duration-500 ease-tih11 group-hover:[clip-path:polygon(25%_0%,75%_0%,100%_50%,75%_100%,25%_100%,0%_50%)] group-hover:scale-105 group-hover:rotate-30 motion-reduce:transition-none motion-reduce:group-hover:[clip-path:polygon(50%_0%,100%_25%,100%_75%,50%_100%,0%_75%,0%_25%)] motion-reduce:group-hover:scale-100 motion-reduce:group-hover:rotate-0">
</div>
</div>
<div class="text-center">
<p class="text-[10px] tracking-[0.08em] text-tih11-muted">Hex<span class="mx-1 text-tih11-acc">→</span><span class="font-bold text-tih11-acc">Wide Hex + Spin</span></p>
<p class="mt-0.75 text-[13px] font-bold text-tih11-text">Lattice Morph</p>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih11-bg: #08080d;
--color-tih11-bg: oklch(0.12 0.008 285);
--color-tih11-text: #f1f5f9;
--color-tih11-text: oklch(0.96 0.005 250);
--color-tih11-muted: #64748b;
--color-tih11-muted: oklch(0.58 0.035 255);
--color-tih11-acc: #e879f9;
--color-tih11-acc: oklch(0.78 0.19 320);
--font-tih11-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih11: cubic-bezier(0.34, 1.56, 0.64, 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-11 {
width: 100%;
min-height: 100svh;
}
.tih-11 ::selection {
background: oklch(0.78 0.19 320);
color: #000;
}
```How this works
Both shapes, one element.
<div class="[clip-path:circle(42%_at_50%_50%)]
transition-[clip-path,scale] duration-500 ease-tih11
group-hover:[clip-path:polygon(10%_0%,90%_0%,100%_10%,100%_90%,90%_100%,10%_100%,0%_90%,0%_10%)]
group-hover:scale-105">The circle is a special case that interpolates to anything; the polygon pairs must match vertex for vertex. Writing them adjacently makes a mismatch a visible diff rather than a runtime mystery.
Why an octagon. Going circle → rectangle cleanly means expressing the rectangle as an eight-point polygon with clipped corners, which is also a better-looking target than a hard square.
Composed, not concatenated. The hexagon's hover state is scale-105 rotate-30 — two utilities compiling to two individual properties, where the CSS version writes transform: scale(1.05) rotate(30deg) and must restate the scale to change the rotation.
Make it yours
- Any shape pair works if the vertex counts match; the customization the CSS version suggests (a ten-point star) is a single utility swap here.
- Spring tension:
ease-[cubic-bezier(0.34,2,0.64,1)]for more overshoot. - Speed:
duration-500→duration-300reads as mechanical,duration-700as liquid. - Add
group-hover:rotate-15to any card — rotation composes with the morph without touching the clip values. - Swap the three photographs in the
bg-[image:…]utilities; each shape's fill is local to its markup, and the radial gradient behind it stays as the fallback.
Gotchas — read before shipping
- Matching vertex counts is the hard requirement. A four-point polygon morphing to a six-point polygon hard-cuts, and nothing warns you.
clip-pathclipsbox-shadowtoo — a glow on a clipped element is invisible outside the path.- Arbitrary clip-path values must use underscores for every space, and percentages must be typed closed-up:
polygon(10%_0%,90%_0%,…). - Keep the frame
overflow-visible: the shapes morph outside the inscribed circle, and a clip on the frame would cut the corners off mid-transition. - The compiler needs literal class strings. A polygon assembled from JS produces no CSS — put varying values in a custom property instead.
- 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+ |
Animatable basic-shape clip-path is Baseline; Safari below 9.1 needs -webkit-clip-path, which Tailwind does not emit for arbitrary properties.