Drag across the photograph and the pixels smear like thick liquid — pushed along your cursor, swirling into eddies, fringing green and magenta where the distortion runs hardest, then slowly flowing back to where they started. Faster movement means deeper distortion.
import LiquifyPhoto from '@crazygl/hero-liquify-photo';
export default function Page() {
return (
<LiquifyPhoto
backgroundImage="https://crazygl.com/samples/leopard-portrait.avif"
heading="Liquify Photo"
pushStrength={1}
returnSpeed={0.55}
/>
);
}backgroundImage (any photo; cover-fitted so any aspect works), imageZoom (keep a little above 1 so the fluid never drags the frame edge into view), overlayDarkness, vignette, grainAmount.brushRadius and pushStrength set how wide and how hard the cursor pushes (the brush itself also widens with pointer speed); swirlAmount turns a straight smear into genuine self-sustaining vortices; advection decides how much the distortion keeps flowing after you stop; returnSpeed how fast pixels ease home; maxDistortion caps how far a pixel can travel; aberration controls the green/magenta fringing on the hardest smears.idleMotion keeps a slow phantom current running before anyone touches it.The distortion always scales with pointer speed, so a slow pass caresses the surface and a fast swipe gouges it. High-detail photographs read best — the effect needs texture to smear.
The heading is bold, large, left-aligned, and stands alone (no subheading, no hover effects) — it defaults to "Liquify Photo" but reads well as any short label.
npm install @crazygl/hero-liquify-photoThe component takes the same props you see in the live customizer on the right — every default ships poster-quality.
import LiquifyPhoto from '@crazygl/hero-liquify-photo';
export default function Landing() {
return (
<LiquifyPhoto />
);
}The wrapper renders static HTML on the server and only initialises the canvas after hydration, so search engines see your copy.
// app/page.tsx — works in SSR-first frameworks (Next, Remix, Astro, etc.)
'use client';
import LiquifyPhoto from '@crazygl/hero-liquify-photo';
export default function Page() {
return (
<section>
<LiquifyPhoto
heading="Say hi."
subheading="Your new hero."
/>
<article>
<h2>Welcome</h2>
<p>Your content keeps its own voice below the hero.</p>
</article>
</section>
);
}