Skip to content
animorio
IT
All components

The metronome slider

Sliders, Physics, SVGGSAP, CSS onlyMediumCompressed weight: Demo 8.7 KBGSAP 28 KBFreeDownload the zip

The tempo slider of a music practice app, in the minimal style: above a thin bar a metronome drawn in hairlines swings at the chosen tempo, with the weight rising on the rod for slow tempos and sliding down for fast ones, a vermilion mark at every beat and a big figure that rolls its digits and grows wider with the tempo.

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 metronome 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 tempo field of a practice app: a slider for the beats per minute, and above it a metronome drawn in
         hairlines that swings at the tempo chosen. As in a real metronome the weight slides up the rod for a slow
         tempo and down for a fast one. The real range input underneath carries the value, the keys and the screen
         reader; a tap on the metronome stops it and starts it again -->
    <div class="tempo" data-tempo>
      <button class="tempo__metro" type="button" aria-pressed="true" aria-label="Pause the metronome" data-metro>
        <svg class="metro" viewBox="0 0 200 220" aria-hidden="true">
          <!-- the two ticks that light at the ends of the swing -->
          <path class="metro__arc" data-arc />
          <path class="metro__tick" data-tick-l />
          <path class="metro__tick" data-tick-r />
          <!-- the case: a tall pyramid in a hairline, with its foot and the face of the scale -->
          <path class="metro__case" d="M74 18 h52 l38 176 h-128 z" />
          <path class="metro__foot" d="M30 194 h140 l6 10 h-152 z" />
          <path class="metro__face" d="M88 40 h24 l20 120 h-64 z" />
          <g class="metro__marks" data-marks></g>
          <!-- the pendulum: rod, weight and pivot; the script turns it round the pivot -->
          <g class="metro__arm" data-arm>
            <line class="metro__rod" x1="100" y1="172" x2="100" y2="26" />
            <g data-weight>
              <path class="metro__weight" d="M91 -7 h18 l3 14 h-24 z" />
              <path class="metro__shine" d="M94 -4 h4 l1 8 h-5.5 z" />
            </g>
          </g>
          <circle class="metro__pivot" cx="100" cy="172" r="3.2" />
        </svg>
      </button>

      <div class="tempo__read" aria-hidden="true">
        <p class="tempo__num" data-num></p>
        <div class="tempo__side">
          <span class="tempo__unit">BPM</span>
          <span class="tempo__name"><span class="tempo__name-text" data-name>Andante</span></span>
        </div>
      </div>

      <div class="tempo__track" data-track>
        <svg class="track" aria-hidden="true" data-track-svg></svg>
        <input class="tempo__range" type="range" id="tempo-range" min="40" max="208" step="1" value="92" aria-label="Tempo, beats per minute" data-range>
      </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.

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

What it does

On a white background there is a metronome drawn in thin grey lines: the pyramid case, the foot and the face with the tempo marks. Inside, the black rod swings from the pivot at the bottom, with a weight edged in vermilion; each end of the swing is a beat, and on the side the pendulum reaches a short vermilion stroke lights for a moment while the rod gives a one-pixel jump. Below, big, the beats per minute, for example 92, with BPM beside it and the tempo’s name in grey italics, Andante. Below that the bar: a thin line, black up to the knob and grey after it, with the tempo marks (Largo, Andante, Allegro, Presto written under them) and the knob, a small upright vermilion bar. Dragging the knob, or tapping anywhere on the bar, changes the tempo: the weight slides on the rod, up for slow tempos and down for fast ones, on a spring that brings it in with a small bounce, and the pendulum speeds up or slows down without ever jumping. The digits roll each in its own column, the figure grows wider with the tempo and the tempo’s name slides when a new one is reached. Tapping the metronome stops it and the rod settles in the middle; tapping again starts it. If nobody touches it, a pretend hand drags the slider by itself between different tempos.

How it works

A phase that never jumps

The pendulum does not follow a clock but a phase that grows at each step by 2π times the frequency (the tempo divided by 120, since a whole swing holds two beats) times the time elapsed. Changing the tempo only changes how fast the phase grows, so the pendulum speeds up or slows down where it is, without a jerk. The angle is SWING times the sine of the phase, times how far the metronome is switched on.

The beat at both ends

A beat is the moment the phase passes a quarter turn plus a whole half turn: the pendulum is then at its widest on one side. The vermilion mark on that side lights and fades in TICK seconds on a squared curve, and the rod jumps by KICK pixels and back: the knock of the mechanism.

The weight on the rod

As in a real metronome the weight sits higher for slow tempos and lower for fast ones: its distance from the pivot goes from 136 to 50 drawing units along the slider. A spring (WEIGHT_SPRING) takes it there and brings it in with a bounce; the marks on the face show where the weight stands for each named tempo.

Digits in columns

The figure is made of three columns, each with the ten digits stacked in a one-line mask: when the number changes every column slides to its digit with back.out, and the hundreds column shrinks to nothing below 100. The figure’s width (Roboto Flex’s font-stretch) goes from WIDTH[0] to WIDTH[1] along the slider.

Springs on the ticker

Knob, weight and the pendulum switching on are springs worked out on GSAP’s ticker in steps of 1/240 of a second, with the frame step capped at 1/30. When the metronome is stopped and nothing moves any more, the ticker is removed, and a touch puts it back.

The real slider and the pretend hand

Under the drawing there is a real, invisible range input that holds the value, the keys (arrows, Page Up and Down, Home, End) and the screen reader, with an aria-valuetext like 92 beats per minute, Andante. After IDLE seconds without a touch a GSAP timeline acts as a pretend hand and drags the knob between six tempos; the first real touch stops it.

Values to change

NameFileDefaultWhat it changes
MIN_BPMscript.js40The slowest tempo.
MAX_BPMscript.js208The fastest tempo.
START_BPMscript.js92The tempo when the page opens.
SWINGscript.js24How far the pendulum swings to each side, in degrees.
WEIGHT_SPRINGscript.js[140, 0.62]The spring of the weight sliding on the rod: how stiff, and how much it is held back.
KNOB_SPRINGscript.js[260, 0.82]The spring of the knob following the hand: how stiff, and how much it is held back.
TICKscript.js0.32How long the vermilion mark of each beat stays lit, in seconds.
KICKscript.js1How far the pendulum jumps at each beat, in pixels of the drawing.
WIDTHscript.js[40, 140]The figure’s width axis at the slowest and at the fastest tempo (25 to 151).
IDLEscript.js2.6Seconds without a touch before the pretend hand moves the slider.
TEMPIscript.js[[60, 'Largo'], [76, 'Adagio'], [108, 'Andante'], [120, 'Moderato'], [168, 'Allegro'], [208, 'Presto']]The tempo names: up to this tempo, this name.

Try them in the Playground

When to use it

For the tempo of a metronome or a practice app, a player’s playback speed, the pace of a workout or any slider whose value is a rhythm and is better seen beating while it is chosen.

On phones

The metronome is sized on the height of the screen (30% at most) and the figure shrinks with it; the bar takes the width minus a margin. A finger drags it sideways while the page still scrolls up and down (touch-action: pan-y), and a tap on the metronome stops and restarts it.

With reduced motion

The pendulum stands still in the middle and there are no beat marks; the weight is at once in its place, the digits change without sliding and the tempo’s name changes at once. The slider works as usual.

Pitfalls

  • Working out the angle as the sine of elapsed time times the frequency made the pendulum jump to a new place at every tempo change: it needs a phase that accumulates step by step.
  • Counting the beat when the sine changes sign put it in the middle of the swing, where real metronomes do not knock: the beat is counted at the two ends, a quarter turn further on.
  • With the weight tied straight to the tempo, a fast drag teleported it along the rod: it follows the knob on a softer spring of its own.

Libraries

GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.

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

Testing

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