Skip to content
animorio
IT
Back to the library

Dose faders

Hover, TextGSAP, CSS onlyMediumCompressed weight: Demo 4.3 KBGSAP + ScrollTrigger 45 KBFreeDownload the zip

Three rows like mixer faders: a coloured band stretches and inside it the same word is dark, so the word changes colour right at the edge. The doses spring up and can be set with the mouse, a finger or the keys.

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 dose sliders</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="pagina">
    <p class="nota" data-nota>Move the mouse over a row: the dose follows the pointer, and the word changes colour right on the edge. You can drag it too, or use the arrow keys.</p>
    <header class="testa">
      <p class="testa__etichetta">The recipe</p>
      <h1 class="testa__titolo">Three doses, by eye.</h1>
    </header>

    <!-- ogni riga è un cursore: una banda colorata che si allunga, con dentro la stessa scritta in scuro -->
    <div class="dosi" data-dosi>
      <div class="dose" data-dose="olio" data-riposo="0.62" role="slider" tabindex="0" aria-label="Oil" aria-valuemin="0" aria-valuemax="100" style="--banda: #D7B24A">
        <span class="dose__nome" aria-hidden="true">Oil</span>
        <div class="dose__banda" data-banda aria-hidden="true"><span class="dose__nome dose__nome--dentro">Oil</span></div>
        <span class="dose__quanto" data-quanto aria-hidden="true"></span>
        <i class="dose__scala" aria-hidden="true"></i>
      </div>
      <div class="dose" data-dose="sale" data-riposo="0.38" role="slider" tabindex="0" aria-label="Salt" aria-valuemin="0" aria-valuemax="100" style="--banda: #B9C7CF">
        <span class="dose__nome" aria-hidden="true">Salt</span>
        <div class="dose__banda" data-banda aria-hidden="true"><span class="dose__nome dose__nome--dentro">Salt</span></div>
        <span class="dose__quanto" data-quanto aria-hidden="true"></span>
        <i class="dose__scala" aria-hidden="true"></i>
      </div>
      <div class="dose" data-dose="peperoncino" data-riposo="0.55" role="slider" tabindex="0" aria-label="Chilli" aria-valuemin="0" aria-valuemax="100" style="--banda: #D8452B">
        <span class="dose__nome" aria-hidden="true">Chilli</span>
        <div class="dose__banda" data-banda aria-hidden="true"><span class="dose__nome dose__nome--dentro">Chilli</span></div>
        <span class="dose__quanto" data-quanto aria-hidden="true"></span>
        <i class="dose__scala" aria-hidden="true"></i>
      </div>
    </div>

    <p class="piede">Grandma’s doses don’t fit on a sheet of paper: you set them by eye, tasting as you go.</p>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.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.

43 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 “Dose faders” from Animorio and fit it into my site

What it does

A recipe in three full-width rows: Olio, Sale, Peperoncino (oil, salt, chilli), set huge and condensed. Each row is a fader: a band in its colour, gold, salt grey, red, stretches from the left, and inside the band the same word is dark, so the word changes colour exactly at the edge. When the rows enter the screen the doses rise to their place one after the other, on a spring, with a small bounce. With the mouse over it the dose follows the pointer; it can be dragged with a finger and set with the arrow keys. At the band’s edge the dose is written in words, “un filo”, “due pizzichi”, “quanto basta”, “troppo” (a drizzle, two pinches, as needed, too much), and at the foot of each row there is a twenty-notch scale.

How it works

The same word twice

In each row the word appears twice, in the same place: a light one on the background, a dark one inside the band. The band is cut by clip-path: inset(0 calc((1 − level) × 100%) 0 0), with the level in a CSS variable: where the band ends the dark word ends too, and the edge cuts the letters in half.

A real spring

The level is a small simulation: acceleration = stiffness × (target − level) − damping × velocity, integrated in 1/240-second steps. On entry the spring is soft (90 and 9) and bounces; when it follows the pointer it is stiff (260 and 30) and arrives without oscillating.

Mouse, finger and keyboard

Mouse movement is heard on the window and finds the row with closest(); a finger drags with setPointerCapture, and touch-action: pan-y still lets the page scroll vertically. Each row is a role="slider" with aria-valuenow and aria-valuetext: the arrows move it by 5, Home and End take it to the ends.

The dose in words

The level is split into six bands, each with its word, different for oil, salt and chilli. The word sits at the band’s edge; beyond 80% it moves inside, dark, because outside it does not fit.

Values to change

NameFileDefaultWhat it changes
MOLLA, SEGUEscript.js90/9, 260/30Stiffness and damping of the spring on entry and while following the pointer.
PAROLEscript.js6 per rigaEach row’s doses in words, from smallest to largest.
data-riposoindex.html0.62, 0.38, 0.55Where each dose settles on entry.
--bandaindex.htmlper rigaEach row’s band colour.

Try them in the Playground

When to use it

For a list of services, ingredients or skills that should feel like a control panel: three or four rows, short words, and something to adjust.

On phones

Rows are shorter and words smaller; the dose is dragged sideways with a finger or set with a tap, while vertically the page scrolls as usual.

With reduced motion

No spring: the doses are already in place and move at once, without bounces.

Pitfalls

  • Colouring the word with a gradient does not cut it sharply at the edge: you need two copies of the word, one inside the band cut by clip-path.
  • If the spring uses the frame time as a single step, at 30 frames per second it becomes unstable: integrate in small fixed steps.
  • With setPointerCapture but without touch-action: pan-y, on a phone every row blocks page scrolling.
  • A fader made of divs is invisible to screen readers: role="slider", aria-valuenow, aria-valuetext and the arrow keys make it real.

Libraries

GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 4.3 KB; the libraries: GSAP + ScrollTrigger 45 KB.

Testing

Tested on 21 October 2026

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

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 animations