Steal this with a prompt:
Build a "Liquid hover" hover animation using CSS + JS.
The product photo turns liquid under the cursor: it swirls and smears as you move, splitting into colour at the fast edges, and settles back when you leave.
Behavior
- Draw each card image with a WebGL2 fragment shader on a canvas the size of its frame (cap devicePixelRatio at 2), the photo uploaded once as a texture. Keep a real <img> or text alternative for the picture; the canvas is aria-hidden.
- Track the pointer over the frame in 0..1 coordinates. Each frame, ease a smoothed position toward it (keep 60% of the gap per 16ms frame, scaled by the real frame time) and derive a smoothed velocity from it, decaying to zero when the pointer stops.
- Hover amount: tween 0 → 1 on pointer enter (or focus) and back on leave, over 500ms on Out quint.
- Per pixel: falloff = exp(−distance² / 0.24²) × hover. Liquid: offset the lookup by two drifting 4-octave value-noise fields (−0.5..0.5) × 0.16 × strength × falloff, minus the pointer velocity × 0.06 × strength × falloff, so the picture swirls and smears behind the pointer like wet paint. Zoom the whole picture 6% × hover so pushed pixels never sample past the edge.
- Colour split: sample red and blue apart along the push direction by (push length × 0.6 + speed × 0.012 × falloff) × 0.5.
- Run one requestAnimationFrame loop per card only while it is hovered, settling, or still moving; stop it when the hover is back to 0 and the velocity has died out. On focus, drift the point slowly around the middle so keyboard users see it too.
Timing
- Duration 500ms, delay 0ms
- Easing: Out quint, cubic-bezier(0.22, 1, 0.36, 1)
Implementation
- Use plain CSS transitions and keyframes. Use IntersectionObserver for in-view triggers, passive scroll listeners throttled with requestAnimationFrame, and the Web Animations API (element.animate) for one-off sequences. No libraries.
- Animate only a WebGL2 fragment shader per image (pointer, velocity and hover uniforms change each frame); nothing in the layout moves so it stays smooth at 60fps.
- Mirror the hover state on :focus-visible. Gate it behind @media (hover: hover) and (pointer: fine) so touch devices skip it or map it to press.
- Reduced motion (prefers-reduced-motion: reduce): No distortion: the photo stays still and only the caption reacts to hover.
Apply it to: [describe your elements, e.g. product or portfolio cards]
@felixleezd Super agree especially when building from zero. Intuition > Data in the beginning, but as you scale, Data become just as, if not more important.
I asked Paper and Figma MCP with Claude Opus 5.5 to recreate new icons based on the reference image (on the right) that I gave.
Who did it better? Paper (top) vs Figma (bottom)