Skip to content
animorio
IT
All components

The ferrofluid slider

Sliders, WebGL, Physics, 3DWebGL, GSAPAdvancedCompressed weight: Demo 14 KBGSAP 28 KBFreeDownload the zip

The bass slider of a speaker made with a puddle of ferrofluid on a glass shelf: under the glass a magnet follows the hand, and more bass means a stronger field, so the black liquid rises from a glossy puddle into a crown of spikes. Dragged fast it falls behind, stretches and its spikes melt and lie back; when the magnet stops it catches up and the spikes spring up again, the middle ones first. The liquid is a 3D shape drawn by a WebGL shader.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The ferrofluid slider</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/host-grotesk@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the bass of a speaker, set with a puddle of ferrofluid on a glass shelf: a magnet under the glass goes where
         the hand takes it, and the stronger its field, the spikier the fluid. The fluid is drawn by a WebGL shader on
         the canvas; the glass, its film and the magnet's mark are plain HTML -->
    <div class="bass" data-bass>
      <div class="bass__head">
        <span class="bass__label" id="bass-label">Bass</span>
        <span class="bass__value" aria-hidden="true"><span class="bass__number" data-number>+9.0</span><span class="bass__unit">dB</span></span>
      </div>
      <div class="bass__track" role="slider" tabindex="0" aria-labelledby="bass-label" aria-orientation="horizontal" aria-valuemin="0" aria-valuemax="12" aria-valuenow="9.0" aria-valuetext="+9.0 dB" data-track data-autoclic>
        <span class="bass__shelf" aria-hidden="true">
          <span class="bass__top"></span>
          <span class="bass__edge"></span>
        </span>
        <span class="bass__film" aria-hidden="true" data-film></span>
        <span class="bass__mark" aria-hidden="true" data-mark></span>
        <canvas class="bass__fluid" aria-hidden="true" data-canvas></canvas>
      </div>
      <!-- the two ends of the range: the script writes them from RANGE -->
      <div class="bass__scale" aria-hidden="true">
        <span data-low></span>
        <span data-high></span>
      </div>
    </div>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

27 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The ferrofluid slider” from Animorio and fit it into my site

What it does

On a white background the word Bass and on the right the value, +9.0 dB. Below, a pale glass shelf seen a little from above, with the green edge of the glass, and on it a puddle of glossy black ferrofluid crowned with spikes, with a warm or cool line of light down each one; from the left end of the shelf to the puddle runs the thin film the liquid leaves on the glass. At the two ends, underneath, Flat and +12 dB. When the page opens the puddle is flat and the film runs out to it, then the magnet comes on: the spikes rise from the middle outwards while the number counts. More bass means a stronger field: at 0 dB the puddle is a smooth lens, then one spike rises in the middle, then the ring round it, and at the top the spikes are tall and fanned out. Dragging, the magnet under the glass goes exactly where the hand goes (a small steel mark under the shelf shows it until the liquid has caught up), but the liquid is heavy: going fast it falls behind, stretches after the magnet, sinks, and its spikes melt and lie back along the field, like grass in a wind; when the magnet stops the liquid catches up, sways a little and the spikes spring up again with a small bounce, the middle ones first. With the mouse over it the spikes stand up a touch, pressing a little more. Pulled past +12 dB the spikes strain and tremble; past 0 the puddle spreads flat. At the ends of the glass the liquid stops and does not fall off. Pressing on the shelf away from the puddle the magnet runs there and the liquid flows after it. The arrows, Page Up and Down, Home and End move it from the keyboard.

How it works

A 3D shape made of distances

The liquid is not a picture: for every pixel a WebGL shader casts a ray from a camera looking down on the shelf by 14 degrees, and moves it on each time by the distance to the nearest shape until it touches it (ray marching). The shape is a squashed ellipsoid, the body of the puddle, plus a cone with hollow flanks for every spike, joined with a smooth minimum: the spikes melt into each other only at their feet (the blend narrows going up) and all of them into the body; the glass cuts it underneath. The shader skips the pixels outside the box the liquid is in.

Ferrofluid spikes

As in real ferrofluid the spikes stand on a hexagonal grid: the middle one, a ring of 6 and one of 12 (SPIKES). Each one points along the field, away from the pole of the magnet under the glass, so they fan out. Its height is a spring chasing the one the field asks for, TALL times the field to the power of 0.85, taller in the middle; the outer spikes only rise in a stronger field. They go up on a loosely held spring (ERUPT) and overshoot; they come down fast and without bouncing, as surface tension pulls them back.

The magnet and the heavy liquid

The magnet follows the hand exactly; the liquid is pulled by it with a damped spring (DRAG), worked out on GSAP's ticker in steps of 1/240 of a second with the frame capped at 1/30. The field it feels falls with the distance from the magnet, e^(−(d/REACH)²): dragged fast the liquid falls behind, stretches towards the magnet, sinks and loses its spikes, which lie back; when the magnet stops it catches up, the field comes back and the spikes rise again. At the ends of the glass a stiff spring stops it: a liquid halts at an edge and does not run over it.

The light of a studio

Once the point is found, the normal comes from the slope of the distance; the colour is the reflection of a studio made of numbers (a round warm softbox up on the left, two tall strips, warm on the left and cool on the right, the ceiling, the white room and the table, light at the horizon), weighed with Fresnel's formula: the liquid is black head on and glossy at the sides, with a line of light down every spike. On the glass, round its foot, a soft shadow and the dark reflection of the liquid, found with a second ray. The lights' colours come from the CSS, made linear.

The slider, the keys and the preview

The slider is the whole strip, with role slider, aria-valuenow and aria-valuetext. The hand holds the magnet: past the ends it gives RUBBER pixels at most and the spikes strain and tremble, or the puddle spreads; pressed away from the puddle it runs there on a stiff spring. The arrows move the value by KEYS[0], with Shift or the Page keys by KEYS[1], Home and End go to the ends. A click from a script (detail 0, the one of the library's preview) is a pretend hand and takes the magnet far away. When nothing moves the loop stops, and with the hand held still the canvas is not drawn again.

Values to change

NameFileDefaultWhat it changes
START_ATscript.js9The bass when the page opens, in dB.
RANGEscript.js[0, 12]The lowest and the highest bass, in dB.
STEPscript.js0.5How much the bass moves at a time.
KEYSscript.js[0.5, 3]How far an arrow key moves the bass, and with Shift or the Page keys.
SPIKESscript.js19How many spikes the liquid can grow: 7, 19 or 37.
TALLscript.js46How tall the middle spike grows at the top of the range, in pixels.
DRAGscript.js[140, 0.6]How the liquid follows the magnet: how stiff the spring is and how much it is held back.
REACHscript.js26How far behind the magnet the liquid can fall, in pixels, before its spikes melt.
ERUPTscript.js[320, 0.28]The spikes' spring: how stiff it is and how much it is held back (little, so they overshoot).
RUBBERscript.js8How far the magnet gives when it is pulled past its two ends, in pixels.

Try them in the Playground

When to use it

For the bass or the volume of a speaker or a music app, the strength of an effect, the power of a vacuum cleaner or a vibration, any force: wherever a value means «more energy» and touching it should surprise. It suits audio sites, industrial design, labs and gadgets.

On phones

The shelf takes the width of the screen minus the margins (358 pixels at 390) and the liquid keeps its size. On the strip a finger drags the magnet without scrolling the page (touch-action: none); outside it the page scrolls. At a touch the field grows as it does when the mouse presses; the spikes standing up under a passing mouse are not there on a phone.

With reduced motion

No lag, no stretching, no bounce or trembling: the liquid always sits on the magnet with its spikes already as tall as the value asks, jumps where you press and goes straight to the value chosen with the keys; when the page opens nothing grows and the number does not count. The shape and the light stay.

Pitfalls

  • To save time, the spikes far from the ray were skipped in the distance: what was left was the body's distance, much larger, the ray jumped over the spikes and some of their tips were left detached, floating over the crown. Now a far spike counts as the ball round it: a distance that never says more than the real one.
  • With the smooth minimum between all the spikes, two close tips made a bridge, a little black dot over the crown: the blend between spikes narrows going up, from 2 pixels at their feet to a quarter of a pixel at the top.
  • A big rectangular softbox was reflected in the hollows between the spikes as flat grey patches, and the white table turned the whole bottom of the puddle grey: the softbox is round and smaller, the long lights are thin strips and the table is light only at the horizon.
  • With 37 spikes the liquid looked like a brush, and the tips of the ones in front, seen end on, became dots: at this size 19 thicker spikes read better as ferrofluid.
  • Sent to an end, the liquid overshot the magnet and ran off the glass: at the ends a stiff spring now stops it, as an edge stops a drop.
  • With the hand held still on the magnet the shader drew the same picture every frame: if the spikes and the liquid have not moved, the canvas is left as it is.

Libraries

GSAP 3.15.0, Host Grotesk (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 14 KB; the libraries: GSAP 28 KB.

Testing

Tested on 6 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All components