Skip to the content

Liquid hover

A picture, or every picture of a grid, turns liquid under the pointer.

Become a member to unlock the full effect today.

Join now

Already a member? Sign in

Documentation

  1. Copy to Webflow

    Add Geist and Geist Mono to your site's fonts (Site settings, Fonts, Google Fonts) before pasting: Webflow removes any font your site has not installed.

  2. Add custom CSS

    The canvas is laid over the marked box and draws its pictures: anything laid over a picture, a badge or a caption, needs position: relative and a z-index over 1 to stay in front. The radius and the object-fit of a picture are read on the picture itself.
  3. Add custom JS

  4. Use it on your own elements

    Custom attributes
    Select the element on the canvas and open the Settings panel. Under Custom attributes, add a pair: the name on the left, the value on the right.
    Custom attributeWhat it does
    data-liquid-hover Marks the box that holds the pictures: a figure, a grid of figures, a whole section. It takes no value: leave the value field empty. One canvas is laid over that box and every picture in it turns liquid, so mark the box around a grid rather than each picture. Put on a picture itself, it is read as the box around that picture. Without it on any element of the page, the embed marks the section it was pasted into.
    data-liquid-hover-image Marks one picture of the box, an Image. It takes no value. Without it on any picture, every picture of the box turns liquid; with it on some, only those do. [ Optional ]
    data-liquid-hover-state Written by the engine on the box: live while a surface moves, idle at rest, still under reduced motion, plain when there is no WebGL or no picture could be read. Never written by hand. [ Optional ]
    data-liquid-hover-live Written by the engine on each picture the canvas draws, which the stylesheet then makes clear. A picture without it is shown by the page itself. Never written by hand. [ Optional ]
    Settings
    Every setting is a custom attribute too, added the same way and on the same element. An attribute always wins over the defaults written in the code.
    AttributeDefaultWhat it is
    data-liquid-hover-tint #ffab1a Colour of the fringe an edge takes on the wave: that colour on one side of the edge, its opposite on the other. Options: any CSS colour, a hex, an rgb(), a name.
    data-liquid-hover-tint-amount 1 How much the fringe follows tint, 0 to 1.
    data-liquid-hover-strength 0.35 How far the picture is pushed at the heart of a full speed pass, in shares of the brush radius.
    data-liquid-hover-radius 0.22 Radius of the brush, in shares of the picture's width.
    data-liquid-hover-relax 0.92 Share of the wave kept from one frame to the next, at 60 frames a second; it sets how long the surface takes to lie flat.
    data-liquid-hover-split 0.14 Gap between the colour layers, in shares of the push.
    data-liquid-hover-velocity 0.6 Share of the gesture's speed in the push, 0 to 1.

What it does

Liquid hover is a cursor animation for Webflow and vanilla JavaScript, with no library. Also called liquid image hover effect, liquid distortion hover effect or image ripple effect on hover.

A picture, or every picture of a grid, turns liquid under the pointer. The gesture pushes the surface of the picture along its own direction, the harder the faster it goes, and the push runs out as a ripple: the picture bends where the pointer passes, a little further for one colour layer than for the other, so every edge on the wave takes a fringe of colour, and the front of the wave catches a touch of light. Then the surface swings back once, softly, and lies flat again in about a second. A click or a tap drops a single wave that opens out from the point. Each picture has its own sheet of points on springs, moved on the processor and drawn by a short WebGL shader, on one canvas for the whole box: no library, no build. At rest the loop stops and the canvas shows the picture the page showed, at the same place and the same size. Without WebGL, under reduced motion, or when a picture comes from another site that does not allow its pixels to be read, the plain HTML picture stays, untouched.

Updated

Questions

Put the custom attribute data-liquid-hover on the box that holds the pictures, a grid or a whole section, and every <img> inside it turns liquid. Mark the box and not each picture: the script lays one canvas over it, because a browser only gives a page a few WebGL contexts. Settings go on that box, for instance data-liquid-hover-strength="0.5".

No. It is raw WebGL1 with the shader written in the engine, no library and no build. Each picture gets a grid of points on springs, 64 on its long side, moved on the processor and drawn in one draw call.

data-liquid-hover-strength sets how far the picture is pushed, 0.35 by default: lower is a shiver, and past 0.6 the picture folds over itself. data-liquid-hover-relax, 0.92 by default, sets how long the surface takes to lie flat: at 0.85 it is flat in half a second, at 0.96 it sloshes for over two seconds.

The server of that picture has to send Access-Control-Allow-Origin, or its pixels cannot be read and the plain HTML picture stays, with no warning. The Webflow CDN sends it. An animated GIF is drawn as its first frame and a <video> is not taken at all.

Yes. A finger drag pushes the surface through touch events, so the page still scrolls under the finger, and a short touch under 10px and 350ms drops a single wave. Under prefers-reduced-motion no canvas is made and the pictures stay as the page set them.