Wave Distort Effect
Original · freeA gentle wave distortion ripples across the image on hover.
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/imgfx-wave-distort.json"use client";
import { useRef } from "react";
import { motion, useInView, useReducedMotion } from "motion/react";
export default function ImgfxWaveDistort() {
const sectionRef = useRef<HTMLDivElement>(null);
const inView = useInView(sectionRef, { once: true, margin: "-80px" });
const reduce = useReducedMotion();
return (
<section className="relative w-full overflow-hidden bg-neutral-50 px-6 py-20 sm:px-10 sm:py-28 dark:bg-neutral-950">
<style>{`
@keyframes imgfxWave_lift {
0% { transform: translateY(10px); opacity: 0; }
100% { transform: translateY(0); opacity: 1; }
}
@keyframes imgfxWave_hint {
0%, 100% { transform: translateX(0); }
50% { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
.imgfxWave_liftEl { animation: none !important; opacity: 1 !important; transform: none !important; }
.imgfxWave_hintEl { animation: none !important; }
.imgfxWave_ripple { opacity: 0 !important; }
}
`}</style>
{/* Hidden SVG carrying the animated displacement filter */}
<svg
aria-hidden="true"
className="pointer-events-none absolute h-0 w-0"
focusable="false"
>
<defs>
<filter
id="imgfxWaveDistortFilter"
x="-20%"
y="-20%"
width="140%"
height="140%"
>
<feTurbulence
type="fractalNoise"
baseFrequency="0.008 0.013"
numOctaves="2"
seed="7"
result="imgfxNoise"
>
<animate
attributeName="baseFrequency"
dur="14s"
values="0.006 0.010; 0.011 0.018; 0.006 0.010"
repeatCount="indefinite"
calcMode="spline"
keyTimes="0; 0.5; 1"
keySplines="0.4 0 0.6 1; 0.4 0 0.6 1"
/>
</feTurbulence>
<feDisplacementMap
in="SourceGraphic"
in2="imgfxNoise"
scale="20"
xChannelSelector="R"
yChannelSelector="G"
/>
</filter>
</defs>
</svg>
<div ref={sectionRef} className="mx-auto max-w-2xl">
<motion.div
initial={reduce ? false : { opacity: 0, y: 16 }}
animate={inView && !reduce ? { opacity: 1, y: 0 } : undefined}
transition={{ duration: 0.6, ease: [0.22, 1, 0.36, 1] }}
>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-indigo-600 dark:text-indigo-400">
Wave Distort
</p>
<h2 className="mt-3 text-2xl font-semibold tracking-tight text-neutral-900 sm:text-3xl dark:text-neutral-50">
Water it, and it moves
</h2>
{/* Image with ripple-on-hover */}
<div className="group imgfxWave_liftEl mt-8 [animation:imgfxWave_lift_0.7s_cubic-bezier(0.22,1,0.36,1)_both]">
<figure className="relative overflow-hidden rounded-2xl ring-1 ring-neutral-900/10 dark:ring-white/10">
{/* Clean base layer */}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/img/gallery/g14.webp"
alt="Sunlit coastal cliffs meeting a calm turquoise sea"
loading="lazy"
draggable={false}
className="block aspect-[4/3] w-full object-cover"
/>
{/* Rippling overlay layer — fades in and distorts on hover */}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/img/gallery/g14.webp"
alt=""
aria-hidden="true"
loading="lazy"
draggable={false}
className="imgfxWave_ripple absolute inset-0 block h-full w-full object-cover opacity-0 transition-opacity duration-500 ease-out group-hover:opacity-100 group-focus-within:opacity-100"
style={{ filter: "url(#imgfxWaveDistortFilter)" }}
/>
{/* Sheen that follows the reveal */}
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-neutral-950/20 to-transparent opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
</figure>
</div>
<p className="mt-4 flex items-center gap-1.5 text-sm text-neutral-500 dark:text-neutral-400">
Hover the photo to send a slow ripple across the surface
<span
className="imgfxWave_hintEl inline-block [animation:imgfxWave_hint_1.6s_ease-in-out_infinite]"
aria-hidden="true"
>
→
</span>
</p>
</motion.div>
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Hover Zoom Effect
OriginalImage zooms in smoothly inside a fixed rounded frame on hover.

Hover Zoom Out Effect
OriginalImage starts zoomed and settles to normal on hover.

Zoom Rotate Effect
OriginalImage zooms and rotates slightly on hover.

Grayscale Color Effect
OriginalGreyscale image turns to full colour on hover.

Color Grayscale Effect
OriginalFull-colour image fades to greyscale on hover.

Blur Sharp Effect
OriginalBlurred image sharpens on hover.

Sharp Blur Effect
OriginalSharp image blurs with a caption appearing on hover.

Sepia Clear Effect
OriginalSepia-toned image clears to full colour on hover.

Saturate Pop Effect
OriginalMuted image saturates and pops on hover.

Contrast Pop Effect
OriginalLow-contrast image gains punchy contrast on hover.

Brightness Lift Effect
OriginalDim image brightens on hover.

Hue Rotate Effect
OriginalImage hue-shifts through colours on hover.

