20 CSS Image Hover Effects 11 / 20
CSS Image Clip-Path Transition Hover
Geometric shape morphing where images transition between circles, diamonds, and polygons via interpolated clip-path values on hover.
The code
<div class="ih-11">
<div class="ih-11__grid">
<div class="ih-11__item">
<div class="ih-11__frame">
<div class="ih-11__img ih-11__img--circle"><span class="ih-11__icon">🌕</span></div>
</div>
<div class="ih-11__labels">
<p><span class="ih-11__shape-from">Circle</span><span class="ih-11__arrow">→</span><span class="ih-11__shape-to">Rounded Rect</span></p>
<p class="ih-11__name">Orbital Shift</p>
</div>
</div>
<div class="ih-11__item">
<div class="ih-11__frame">
<div class="ih-11__img ih-11__img--diamond"><span class="ih-11__icon">💎</span></div>
</div>
<div class="ih-11__labels">
<p><span class="ih-11__shape-from">Diamond</span><span class="ih-11__arrow">→</span><span class="ih-11__shape-to">Circle</span></p>
<p class="ih-11__name">Gem Reveal</p>
</div>
</div>
<div class="ih-11__item">
<div class="ih-11__frame">
<div class="ih-11__img ih-11__img--hexagon"><span class="ih-11__icon">⬡</span></div>
</div>
<div class="ih-11__labels">
<p><span class="ih-11__shape-from">Hex</span><span class="ih-11__arrow">→</span><span class="ih-11__shape-to">Wide Hex + Spin</span></p>
<p class="ih-11__name">Lattice Morph</p>
</div>
</div>
</div>
</div> <div class="ih-11">
<div class="ih-11__grid">
<div class="ih-11__item">
<div class="ih-11__frame">
<div class="ih-11__img ih-11__img--circle"><span class="ih-11__icon">🌕</span></div>
</div>
<div class="ih-11__labels">
<p><span class="ih-11__shape-from">Circle</span><span class="ih-11__arrow">→</span><span class="ih-11__shape-to">Rounded Rect</span></p>
<p class="ih-11__name">Orbital Shift</p>
</div>
</div>
<div class="ih-11__item">
<div class="ih-11__frame">
<div class="ih-11__img ih-11__img--diamond"><span class="ih-11__icon">💎</span></div>
</div>
<div class="ih-11__labels">
<p><span class="ih-11__shape-from">Diamond</span><span class="ih-11__arrow">→</span><span class="ih-11__shape-to">Circle</span></p>
<p class="ih-11__name">Gem Reveal</p>
</div>
</div>
<div class="ih-11__item">
<div class="ih-11__frame">
<div class="ih-11__img ih-11__img--hexagon"><span class="ih-11__icon">⬡</span></div>
</div>
<div class="ih-11__labels">
<p><span class="ih-11__shape-from">Hex</span><span class="ih-11__arrow">→</span><span class="ih-11__shape-to">Wide Hex + Spin</span></p>
<p class="ih-11__name">Lattice Morph</p>
</div>
</div>
</div>
</div>.ih-11,.ih-11 *,.ih-11 *::before,.ih-11 *::after{margin:0;padding:0;box-sizing:border-box}
.ih-11 ::selection{background:#e879f9;color:#000}
.ih-11{
--accent:#e879f9;--bg:#08080d;--text:#f1f5f9;--muted:#64748b;
--duration:0.5s;--ease:cubic-bezier(0.34,1.56,0.64,1);
font-family:system-ui,sans-serif;background:var(--bg);padding:40px 24px;
min-height: 100vh;display:flex;align-items:center;justify-content:center;
}
.ih-11__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;max-width:780px;width:100%}
.ih-11__item{display:flex;flex-direction:column;align-items:center;gap:12px;cursor:pointer}
/* clip-path morphs the image shape on hover */
.ih-11__frame{
width:100%;aspect-ratio:1;position:relative;overflow:visible;
}
.ih-11__img{
width:100%;height:100%;display:flex;align-items:center;justify-content:center;
transition:clip-path var(--duration) var(--ease), transform var(--duration) var(--ease);
}
/* Starting shapes */
.ih-11__img--circle{
clip-path:circle(42% at 50% 50%);
background:radial-gradient(circle,#2d1b69,#4c1d95,#7c3aed);
}
.ih-11__img--diamond{
clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%);
background:radial-gradient(circle,#042f2e,#065f46,#34d399);
}
.ih-11__img--hexagon{
clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
background:radial-gradient(circle,#1c1917,#92400e,#f59e0b);
}
/* Hover shapes */
.ih-11__item:hover .ih-11__img--circle{
clip-path:polygon(10% 0%,90% 0%,100% 10%,100% 90%,90% 100%,10% 100%,0% 90%,0% 10%);
transform:scale(1.05);
}
.ih-11__item:hover .ih-11__img--diamond{
clip-path:circle(48% at 50% 50%);
transform:scale(1.05);
}
.ih-11__item:hover .ih-11__img--hexagon{
clip-path:polygon(25% 0%,75% 0%,100% 50%,75% 100%,25% 100%,0% 50%);
transform:scale(1.05) rotate(30deg);
}
.ih-11__icon{font-size:44px;opacity:0.5}
/* Shape label */
.ih-11__labels{text-align:center}
.ih-11__shape-from{font-size:10px;color:var(--muted);letter-spacing:0.08em}
.ih-11__arrow{color:var(--accent);margin:0 4px}
.ih-11__shape-to{font-size:10px;color:var(--accent);font-weight:700}
.ih-11__name{font-size:13px;font-weight:700;color:var(--text);margin-top:3px}
@media(prefers-reduced-motion:reduce){.ih-11__img{transition:none}} .ih-11,.ih-11 *,.ih-11 *::before,.ih-11 *::after{margin:0;padding:0;box-sizing:border-box}
.ih-11 ::selection{background:#e879f9;color:#000}
.ih-11{
--accent:#e879f9;--bg:#08080d;--text:#f1f5f9;--muted:#64748b;
--duration:0.5s;--ease:cubic-bezier(0.34,1.56,0.64,1);
font-family:system-ui,sans-serif;background:var(--bg);padding:40px 24px;
min-height: 100vh;display:flex;align-items:center;justify-content:center;
}
.ih-11__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;max-width:780px;width:100%}
.ih-11__item{display:flex;flex-direction:column;align-items:center;gap:12px;cursor:pointer}
/* clip-path morphs the image shape on hover */
.ih-11__frame{
width:100%;aspect-ratio:1;position:relative;overflow:visible;
}
.ih-11__img{
width:100%;height:100%;display:flex;align-items:center;justify-content:center;
transition:clip-path var(--duration) var(--ease), transform var(--duration) var(--ease);
}
/* Starting shapes */
.ih-11__img--circle{
clip-path:circle(42% at 50% 50%);
background:radial-gradient(circle,#2d1b69,#4c1d95,#7c3aed);
}
.ih-11__img--diamond{
clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%);
background:radial-gradient(circle,#042f2e,#065f46,#34d399);
}
.ih-11__img--hexagon{
clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
background:radial-gradient(circle,#1c1917,#92400e,#f59e0b);
}
/* Hover shapes */
.ih-11__item:hover .ih-11__img--circle{
clip-path:polygon(10% 0%,90% 0%,100% 10%,100% 90%,90% 100%,10% 100%,0% 90%,0% 10%);
transform:scale(1.05);
}
.ih-11__item:hover .ih-11__img--diamond{
clip-path:circle(48% at 50% 50%);
transform:scale(1.05);
}
.ih-11__item:hover .ih-11__img--hexagon{
clip-path:polygon(25% 0%,75% 0%,100% 50%,75% 100%,25% 100%,0% 50%);
transform:scale(1.05) rotate(30deg);
}
.ih-11__icon{font-size:44px;opacity:0.5}
/* Shape label */
.ih-11__labels{text-align:center}
.ih-11__shape-from{font-size:10px;color:var(--muted);letter-spacing:0.08em}
.ih-11__arrow{color:var(--accent);margin:0 4px}
.ih-11__shape-to{font-size:10px;color:var(--accent);font-weight:700}
.ih-11__name{font-size:13px;font-weight:700;color:var(--text);margin-top:3px}
@media(prefers-reduced-motion:reduce){.ih-11__img{transition:none}}How this works
CSS clip-path can be transitioned between two polygon(), circle(), or inset() values as long as both shapes have the same number of vertices. This restriction means a circle must be converted to an equivalent polygon (e.g. an octagon) if the target shape is polygonal, OR the transition must go between two circles of different radii. The browser interpolates each vertex coordinate independently, creating smooth morphing.
The spring easing cubic-bezier(0.34, 1.56, 0.64, 1) overshoots slightly before settling, making the shape morph feel elastic and playful. A transform: scale(1.05) fires simultaneously to keep the clipped area from shrinking visually during the shape change.
Customize
- Use
polygon()throughout for all shapes — this gives you full vertex control and avoids the "equal vertex count" limitation when mixing shape types. - Create a star shape at rest:
polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)and morph to circle. - Pair the clip-path morph with a background gradient rotation via a
@keyframesanimation for continuously shifting colour behind the shape. - Use
clip-pathon a duplicate background layer (via pseudo-element) while keeping the original visible, for a "cookie cutter" reveal effect. - Adjust the spring tension by modifying the bezier:
cubic-bezier(0.34, 2.0, 0.64, 1)increases overshoot for a more bouncy morph.
Watch out for
- Both the start and end
clip-pathvalues MUST have the same number of coordinate pairs for the transition to interpolate — mixing a 4-point polygon with a 6-point polygon will cause a hard cut, not an animation. clip-pathdoes not create a new stacking context but does paint the clipped area, meaningbox-shadowis also clipped and won't be visible outside the path.- In Chrome below 88,
clip-pathtransitions on elements inside CSS grid or flex containers can trigger full layout recalculation — usetransformto isolate.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 55+ | 9.1+ (prefixed) | 54+ | 55+ |
Prefix with -webkit-clip-path for Safari compatibility. The transition between shapes requires equal vertex counts.