Skip to content
animorio
IT
All components

The toffee sweetness slider

Sliders, PhysicsCanvas, GSAPAdvancedCompressed weight: Demo 15 KBGSAP 28 KBFreeDownload the zip

How sweet a cake should be, chosen on a ball of soft toffee: pulled away from a dollop of caramel resting on baking paper, it draws a thread behind it that stretches, thins, bows under its weight and shines. Pushed back, the slack thread droops and draws itself in slowly, like warm caramel. The colour goes from a bitter burnt brown to blond, and the word above gets fatter and softer with the sweetness.

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 toffee sweetness slider</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- how sweet a patisserie makes your cake, chosen on a ball of soft toffee. A dollop of caramel sits at the
         start of a strip of baking paper; the knob is a glossy toffee ball pulled out of it, and the slider's fill is
         the thread of caramel that stretches between the two. The paper, the dollop, the thread and the ball are drawn
         by the script on the canvas; the real range input underneath carries the value, the keys and the screen
         reader -->
    <div class="sweet" data-sweet>
      <div class="sweet__head">
        <label class="sweet__label" for="sweet-range">Sweetness</label>
        <span class="sweet__note" aria-hidden="true"><span class="sweet__note-text" data-note>Our house recipe</span></span>
      </div>
      <p class="sweet__word" aria-hidden="true" data-word>Balanced</p>
      <div class="sweet__track" data-track data-autoclic>
        <canvas class="sweet__canvas" aria-hidden="true" data-canvas></canvas>
        <input class="sweet__range" type="range" id="sweet-range" name="sweetness" min="1" max="5" step="1" value="3" data-range>
      </div>
      <div class="sweet__scale" aria-hidden="true">
        <span data-lo>Bitter</span>
        <span data-hi>Very sweet</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.

38 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 toffee sweetness slider” from Animorio and fit it into my site

What it does

On a white background the word Sweetness and on the right, small and grey, a note on what that sweetness tastes of (Our house recipe). Below it, large, the word for the chosen sweetness, Balanced, in caramel-coloured Fraunces. Further down a strip of ivory baking paper with five printed marks: on the left a glossy dome of caramel, and halfway along a ball of soft toffee with a window reflection, a swirl of cream and its shadow on the paper, with an amber patch beside it where the light comes through the caramel. Between the dollop and the ball runs a thread of caramel that widens where it meets them both and bows a little in the middle. When the page opens the ball grows out of the dollop and is pulled out to Balanced, with the thread stretching behind it. Dragged to the right the thread gets longer, thinner and paler; pulled fast it stays taut, thins most by the ball and breaks into beads, then the caramel flows to its new length and hangs softly again. Pushed to the left the extra thread goes slack and droops towards the paper, then draws itself back into the ball and the dollop and rises again, slow and viscous. The ball rolls (the cream turns inside it), stretches as it runs and wobbles when it stops; under the pointer it swells a little and pressed it squashes. The caramel goes from the burnt brown of Bitter to the blond of Very sweet, the reflections run along the thread as it moves and the marks already passed take on the caramel colour. The word above changes with the ball: the old one melts into its line letter by letter, the new one oozes up out of it and settles with a bounce, and meanwhile it gets fatter, rounder and paler with the sweetness.

How it works

A thread of weights

The thread is a chain of 28 weights under Verlet integration: the first is fixed on the dollop, the last is tied to the ball. Every two neighbouring weights are held by a distance constraint, stiff against stretching and almost loose against squeezing, so a slack thread bends and falls instead of pushing. The viscosity pulls each weight’s speed towards its neighbours’, so the waves are slow and thick.

Caramel that flows

Each piece’s rest length is not fixed: it flows towards the length the thread wants (the distance from the dollop to the ball with the little extra it needs to hang) in FLOW seconds, and a piece stretched past the elastic limit of STRETCH yields and grows longer too. It is a Maxwell spring with a threshold: the thread’s own weight is not enough to make it run. The extra thread of a push back is taken in mostly by the ball and the dollop, so the thread droops, then draws itself in.

Thickness from volume

The thickness comes from the caramel there is: the longer the thread the thinner it is (between THICK[0] and THICK[1]), and where a piece is stretched past its rest length it necks, where it is squeezed it swells. After a quick pull the beads sit on the caramel itself and travel with it; at both ends the thread widens into a fillet that runs into the dollop and the ball.

Drawing on the canvas

Every frame the chain goes through a Catmull-Rom curve and is drawn in four passes: the dark edge, the body, the light inside the caramel and the shine, each in the colour of its thickness (thin caramel lets more light through and looks blonder). The shine is strongest where the thread faces the lamp, so glints run along the thread as it sways. The ball has the gradients of a sphere, the light passing through it, the edge in shade, the reflected window and a swirl of cream worked out on a real sphere and turned as far as it has rolled.

The word

The word moves on Fraunces’ weight and SOFT axes with the caramel, and from Sweet on it switches on WONK, which tips the letters a little. When it changes, each letter of the old one squashes down to the line, spreading, and the letters of the new one ooze up out of it on an elastic spring; if a change comes while the last is still on its way the old drip is skipped, so there are never two words at once.

The real field, the keys and the preview

Under the drawing there is a real, invisible range input: it carries the value, the arrows, Page Up and Down, Home and End and what the screen reader reads (the word and the note). The focus ring shows only when it is reached with the keys. The physics runs on GSAP’s ticker in steps of 1/240 of a second and stops when everything is still. A click from a script (detail 0, the preview’s) is a pretend hand: it pulls the ball all the way out, back to Bitter and then where it was.

Values to change

NameFileDefaultWhat it changes
START_ATscript.js3The sweetness when the page opens, from 1 (the first word) to the last.
WORDSscript.js['Bitter', 'Lightly sweet', 'Balanced', 'Sweet', 'Very sweet']The sweetness words, from the first mark to the last: as many words, as many marks.
NOTESscript.js['Dark cocoa, no glaze', 'A spoon of wildflower honey', 'Our house recipe', 'Salted caramel drizzle', 'Double caramel and fudge']The note at the top right for each sweetness: what that cake tastes of.
BALLscript.js20The radius of the toffee ball, in pixels.
THICKscript.js[5.2, 2.3]Half the thread’s thickness when it is shortest and when it is longest, in pixels.
SAGscript.js1How heavy the thread is: higher, and it bows lower when still and falls faster when slack.
FLOWscript.js0.42How many seconds the caramel takes to flow to its new length: higher, and it stays taut and thin longer after a pull and draws back more slowly.
STRETCHscript.js0.06How far the caramel stretches before it starts to flow, as a share of its length.
BEADSscript.js1How strongly a quick pull breaks the thread into beads (0 never).
SPRINGscript.js[380, 0.42]The spring that takes the ball to its mark when nobody holds it: how stiff, and how much it is held back.

Try them in the Playground

When to use it

For the sweetness of a cake to order at a patisserie or in a delivery app, the sugar in coffee or tea, how dark the caramel should be in a sweet shop, or any choice on a soft scale where the value should make your mouth water.

On phones

The slider takes the width of the screen minus a margin and the ball reaches the end of the paper; the big word drops to 44 pixels. A finger drags it sideways while the page still scrolls up and down (touch-action: pan-y); a tap on the paper sends the ball there, running and then following the finger. Physics, beads and reflections are the same.

With reduced motion

No physics, no entrance, no rolling or wobbling: the ball is at once on its mark and the thread already hangs still, as thick as its length says. The caramel colour still changes, and the word and the note change with a fade.

Pitfalls

  • With the rest length always flowing towards the real one, the thread’s own weight stretched it a little, the thread flowed and in two seconds it lay on the paper: now only a piece stretched past the elastic limit flows.
  • Distance constraints only hold a thread so far, and a hundredth of extra length already makes a deep belly: a taut thread carries its weight in its tension, so gravity grows with how slack the thread is.
  • Pushed back fast, the extra thread made loops in the air and came out on the other side of the ball: now it does not resist squeezing, never goes past the ball’s middle or above its two ends, softens when slack, and the extra caramel is taken in mostly by the ball and the dollop.
  • The thread’s shadow drawn in pieces with round ends overlapped into a row of dots: shadows, shines and swirls are whole strokes or pieces with square ends.
  • The word dropping in from above inside a clipped box showed half letters, and a quick drag over three marks piled them up: now the letters melt down and ooze up from the line, and a change that comes during another skips the drip.
  • The focus ring showed with the mouse too, because the click gives the field focus from a script: it shows only if the last gesture was a key.

Libraries

GSAP 3.15.0, Fraunces (font variabile) 5.3.0.

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

Testing

Tested on 17 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