Skip to content
animorio
IT
All components

The comb slider

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

A project budget in a studio’s contact form, chosen on a comb of thin teeth: the vermilion knob stands among them, the teeth ahead bend under its push and grow, then slip behind it and ring like a plucked comb, with a wave that runs along the row and dies out. The big figure above grows wider with the budget. Minimal style.

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 comb slider</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the budget field of a studio's contact form, on a comb: a row of hairline teeth on a spine. The knob stands
         among the teeth; as it passes they lean out of its way and grow, each on a spring of its own and tied to its
         neighbours, so they straighten behind it in a wave that dies out. The teeth and the knob are drawn by the
         script on the canvas; the real range input underneath carries the value, the keys and the screen reader -->
    <div class="budget" data-budget>
      <div class="budget__head">
        <label class="budget__label" for="budget-range">Project budget</label>
        <span class="budget__note" aria-hidden="true"><span class="budget__note-text" data-note>A full website</span></span>
      </div>
      <p class="budget__value" aria-hidden="true"><span class="budget__cur">€</span><span class="budget__num" data-num>40k</span></p>
      <div class="budget__comb" data-comb data-autoclic>
        <canvas class="budget__canvas" aria-hidden="true" data-canvas></canvas>
        <input class="budget__range" type="range" id="budget-range" name="budget" min="5000" max="100000" step="5000" value="40000" data-range>
      </div>
      <div class="budget__scale" aria-hidden="true">
        <span data-lo>€5k</span>
        <span data-hi>€100k+</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.

37 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 comb slider” from Animorio and fit it into my site

What it does

On a white background the words Project budget and on the right, in grey, what that much usually buys: A full website. Below, big, €40k in Roboto Flex. Below that a comb: a thin line with a row of teeth, a taller one for every step of 5,000 euros and two shorter ones between, black up to the knob and pale grey after it; the knob is a vermilion bar standing among the teeth, and the ones near it are a little taller, like a small crown. At the two ends €5k and €100k+. When the page opens the line draws itself, the teeth come up one after the other and the knob rises at the start of the comb and runs to 40k while the figure counts. Dragging the knob (or pressing anywhere on the comb) pushes the teeth ahead of it, which bend, bunch up a little against it and grow; once a tooth is bent far enough it slips behind with a snap and rings, and the ringing passes to its neighbours and runs along the comb as a wave that dies out. The faster the knob runs, the more the teeth bend before they let it through; its head lags behind and swings once when it stops. Let go, the knob goes to the nearest step, a pixel past and back. The figure at the top grows wider with the budget, narrow at 5k and very wide at 100k+, and gets thinner while the knob runs; the grey line changes with a short slide: A landing page, A full website, A brand and a website, A digital product. Under the pointer the knob grows a little, and held it squashes.

How it works

A row of tied pendulums

Every tooth is a weight on a spring (TOOTH_SPRING) that wants it straight, and two springs tie it to its neighbours (COUPLING): the difference between a tooth and the two beside it pulls it. It is the discrete string of the physics books, so a bend that is not shared does not stay put but runs along the row as a wave, and the damping puts it out in a second and a half. The springs are worked out on GSAP’s ticker in steps of 1/240 of a second, with the frame step capped at 1/30.

The knob is solid

The tip of each tooth stays CLEAR pixels from the middle of the knob, on the side the tooth is on: a very stiff contact spring keeps it out. So the running knob pushes the tips ahead of it and bends those teeth; once one is bent by SLIP of its length it changes side, the contact spring snaps it across and it rings. The slower the knob, the sooner the teeth let it through; a tooth whose root is right behind a still knob stands straight, hidden by it.

The drawing

Every frame the canvas redraws the teeth as quadratic Bézier curves that leave the root straight and bend at the tip, like a real blade; a bending tooth also gets a little lower. Four strokes in all: tall and short teeth, black before the knob and grey after it. The teeth near the knob grow by LIFT (more while it runs, when it is touched or held), and the run drags them a little with it (DRAG). When everything is still, the ticker is removed.

The knob and the hand

While it is held the knob follows the hand on a very stiff spring, just behind; past the two ends it only gives a little. Let go, the value comes from where the hand was, and the KNOB_SPRING spring takes it to the nearest step with one pixel too many. Its head has a spring of its own that makes it lag during the run and swing once on arrival.

The figure on its axes

The figure follows the knob, not the written value: its width axis (Roboto Flex’s font-stretch, 25 to 151) goes from WIDTH[0] to WIDTH[1] along the comb, so it grows while you drag, and its weight drops to 360 with the speed and comes back to 620 when it settles. The grey line above changes by sliding in its mask, up when the budget rises and down when it falls.

The real slider, the keys and the preview

Under the canvas there is a real, invisible range input that holds the value, the label, the keys (arrows, Page Up and Down, Home, End) and the screen reader, with an aria-valuetext like €40,000; the focus ring is drawn only when it is reached with the keys. A click from a script (detail 0, the preview’s) is a pretend hand: it takes the budget to 90k, then down to 15k and back where it was.

Values to change

NameFileDefaultWhat it changes
MINscript.js5000The smallest budget.
MAXscript.js100000The largest budget, written with a plus: that much or more.
STEPscript.js5000How much the budget moves by: one tall tooth for every step.
START_ATscript.js40000The budget when the page opens.
CURRENCYscript.js'€'The sign in front of the figures.
TEETHscript.js3How many teeth there are from one step to the next (fewer on a narrow screen, if they would crowd).
CLEARscript.js5.5How close a tooth’s tip may come to the middle of the knob, in pixels.
SLIPscript.js0.4How far a tooth bends before the knob, as a share of its length, before it slips behind.
LIFTscript.js18How much the teeth near the knob grow, in pixels.
REACHscript.js44How far from the knob the teeth still feel it, in pixels.
DRAGscript.js0.006How much the running knob drags the nearby teeth with it.
TOOTH_SPRINGscript.js[300, 0.22]Each tooth’s spring: how stiff, and how much it is held back (less means it rings longer).
COUPLINGscript.js700How hard each tooth pulls its neighbours: the higher, the faster and farther the wave runs.
KNOB_SPRINGscript.js[320, 0.78]The knob’s spring when nobody holds it: how stiff, and how much it is held back.
WIDTHscript.js[32, 148]The figure’s width axis at the smallest and at the largest budget (25 to 151).
NOTESscript.js[[15000, 'A landing page'], [40000, 'A full website'], [70000, 'A brand and a website'], [100000, 'A digital product']]What a budget usually buys: up to that much, those words.

Try them in the Playground

When to use it

For the budget in a studio’s or an agency’s contact form, the figure of a quote, the text size in a reading app, or any stepped slider where the gesture should be felt in the fingers without adding anything to the page.

On phones

The slider takes the width of the screen minus a margin and the figure gets a little smaller; if the teeth would stand less than 5 pixels apart, there are fewer between two steps. A finger drags it sideways while the page still scrolls up and down (touch-action: pan-y), and a tap on the comb brings the knob there through the teeth. Springs and waves are the same.

With reduced motion

No springs, no waves, no entrance: the knob is at once where it is taken, the nearby teeth are already at their height and bent out of its way, and the figure and the grey line change with a fade. The figure’s width still follows the budget.

Pitfalls

  • With a soft force field pushing the teeth away from the knob, as it passed they moved from one side to the other smoothly and nothing rang: it took a real contact, with the tooth staying on one side until it slips to the other.
  • At rest, a tooth with its root right under the knob stayed bent and its tip poked out on the right like a loose scrap: when the knob is slow, the teeth rooted behind it do not feel it and stand straight, hidden.
  • With a wide white halo round the knob the bent teeth looked broken: the halo is a hairline, and the teeth pass behind the knob.
  • A long jump of the knob (a click at the far end of the comb) threw the teeth at its own speed and made them spin almost flat: a tooth’s tip goes no faster than 560 pixels a second and its bend is never more than three quarters of its length.
  • Focusing the input on touch, so the arrows work after a drag, made Chrome show the focus ring with the mouse too: the ring is drawn only if the last gesture was a key.
  • A click on the Project budget label reaches the input with detail 0, like the preview’s, and would have set the pretend hand going: the pretend hand only starts from a click on the comb.

Libraries

GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.

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

Testing

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