Skip to content
animorio
IT
Back to the library

The syllable metronome

SVG, TextGSAPAdvancedCompressed weight: Demo 10 KBGSAP 28 KBFreeDownload the zip

A metronome drawn in thin lines, in the minimal style: the rod swings like a real pendulum and on every beat a syllable falls onto the line and takes on weight. The last syllable of the bar is the accent, in vermilion. You can drag the weight on the rod: higher is slower, lower is faster, and the BPM figure changes its width and weight 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>Metronome</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage aria-label="A metronome. On every beat a syllable falls onto the line; the last one of the bar is accented.">
    <!-- the hairlines: the line the syllables land on and the metronome, drawn by the script -->
    <svg class="scene" data-scene aria-hidden="true">
      <path class="rule" data-rule d="" />
      <g data-ticks></g>
      <g data-metro>
        <path class="floor" data-floor d="" />
        <g data-swing>
          <path class="arc" data-arc d="" />
          <path class="mark" data-mark-l d="" />
          <path class="mark" data-mark-r d="" />
          <path class="flash" data-flash-l d="" />
          <path class="flash" data-flash-r d="" />
        </g>
        <path class="body" data-body d="" />
        <path class="scale" data-scale d="" />
        <g data-rod>
          <path class="rod" data-rod-line d="" />
          <path class="weight" data-weight d="" />
        </g>
        <path class="pivot" data-pivot d="" />
      </g>
    </svg>

    <!-- the syllables, one span each, built by the script -->
    <div class="words" data-words aria-hidden="true"></div>
    <span class="probe" data-probe aria-hidden="true"></span>

    <!-- the handle on the metronome: drag it up and down, or use the arrow keys -->
    <div class="grip" data-grip role="slider" tabindex="0" aria-label="Tempo" aria-valuemin="40" aria-valuemax="208" aria-valuenow="72" aria-valuetext="72 beats per minute"></div>

    <p class="tempo" data-tempo aria-hidden="true">
      <span class="tempo__num" data-bpm>72</span>
      <span class="tempo__meta">
        <span class="tempo__unit">BPM</span>
        <span class="tempo__window"><span class="tempo__name" data-name>Adagio</span></span>
      </span>
    </p>

    <p class="hint" data-hint aria-hidden="true">Drag the weight to change the tempo</p>
  </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.

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

What it does

On a warm white page a thin line draws itself and on it, to the left, a metronome made only of lines: the pyramid body, a scale of marks, the diamond pivot, the rod rising and the weight sliding down the rod to its tempo with a hair of bounce. The BPM figure counts along with the weight. The rod is pulled aside, held for an instant and let go: it swings like a real pendulum, slow at the ends and fast in the middle, and at each end it beats a tick that flicks the mark at the end of the arc. Before the word, as many small marks as syllables appear under the line, the last one in vermilion. On every beat a syllable falls from above, light and narrow, lands exactly on the tick, squashes, widens on the wdth axis and takes on weight on the wght axis; the line gives a couple of pixels under it and the syllables already down feel the hit. The last one, on the last beat of the bar, is the accent: the heaviest, in vermilion, and the mark at the end of the arc lights up in vermilion too. Then the syllables close up into the whole word with a small settle, lose their weight and rise away; the weight slides by itself to the tempo of the next word and the rod speeds up or slows down without losing the beat: cadenza in Adagio, syncopation in Andante, allegro in Allegro. You can take hold of the metronome and drag up and down: the weight moves, the tempo changes at once, the figure gets narrower and blacker when the tempo is fast, wider and lighter when it is slow, and the name of the tempo rolls over.

How it works

A bar measured in beats

The whole direction is one paused GSAP timeline whose time is not in seconds but in beats: syllable k of the word falls between beat b0 + k − 0.42 and b0 + k, the word closes up half a beat after the accent, the next one starts REST beats later. The timeline's timeScale is the tempo divided by 60: at 72 BPM a beat lasts 0.83 seconds, at 144 half that. When the timeScale changes GSAP keeps the playhead where it is, so the tempo can change at any moment without a jump.

The pendulum

The rod's angle is SWING · cos(π · t), with t the timeline's time in beats: on even beats the rod is all the way right, on odd beats all the way left, still for an instant at the ends and fast in the middle, like a real pendulum. The tick fires when t passes a whole number; the mark at that end of the arc lights up and fades. The rod is a curve that bends a pixel outwards at the ends, where the acceleration is highest, and more at fast tempos. So that the loop comes back identical, the whole cycle always has an even number of beats.

The weight and the tempo

The weight's place on the rod is a number u between 0 (low, 208 BPM) and 1 (high, 40 BPM), and the tempo is 208 · (40 / 208)^u: a logarithmic scale, like the marks on a real metronome, closer together at fast tempos. When you drag, the pointer's vertical travel becomes u; the weight follows it with a small lag, so the tempo changes smoothly too. The arrow keys change the tempo by 2 BPM (10 with Shift).

The syllable that takes on weight

Every syllable is a span inside another: the outer one moves and squashes, the inner one carries the wght and wdth axes of the Archivo variable font. It falls light (wght 150) and narrow (wdth down to 84); on the tick it jumps to wdth 118 and a height of 0.86, then goes back to 100 and 1 on an elastic spring, while its weight rises to 560 (860 for the accent). Each syllable's width is measured at its final weight, and the outer span has that width with the text centred, so changing the axes does not shift the word.

The line that gives

The line is an SVG path redrawn at every frame: when no syllable is landing it is a straight line, otherwise a point every 5 pixels with, under each syllable that has just landed, a Gaussian bell a couple of pixels deep that flattens out on the same spring. The metronome is drawn in its own units (the body is 100 tall) with vector-effect: non-scaling-stroke, so the lines stay thin at any screen size.

Values to change

NameFileDefaultWhat it changes
WORDSscript.js['ca-den-za', 'syn-co-pa-tion', 'al-le-gro']The words, one per bar: the hyphens split the syllables, one falls on every beat and the last one is the accent (up to 6 words of 8 syllables).
TEMPIscript.js[72, 104, 144]The tempo of each word in beats per minute, 40 to 208: the weight slides there by itself before the word starts (until someone drags it).
SWINGscript.js26How many degrees the rod swings to each side.
RESTscript.js4How many empty beats after the accent before the next word: in them the word closes up, stays to be read and leaves.
LIGHTscript.js150The weight of a syllable while it falls (100 to 900).
HEAVYscript.js560The weight it takes on when it lands (100 to 900).
ACCENTscript.js860The weight of the accented syllable, the last of the bar (100 to 900).
SPRINGscript.js1How springy every landing is: 0.4 lands dead, 2 wobbles for longer.

Try them in the Playground

When to use it

For a site that lives on rhythm: a music school, a festival, a practice app, a podcast, the title of a page about tempo and metre. Also as the header of a diction lesson or of a page about words broken into syllables. The metronome with the draggable weight is a real control too: it can be used to pick a value.

On phones

The same animation with the sizes adapted: the metronome stands at the top in the middle on its own base, the line with the syllables below it, nearly as wide as the screen, and the tempo under the line. You drag the weight with a finger, up and down on the metronome.

With reduced motion

Nothing swings and nothing falls: the rod stays upright and on every beat the mark on one side and then the other fades in; the syllables fade in already in their place in the word and already at their weight, the accent in vermilion, and the word fades out. The weight can still be dragged, and it moves without sliding.

Pitfalls

  • With the timeline measured in seconds, changing the tempo once was enough for the syllables to stop landing on the tick. Measured in beats, with the timeScale equal to BPM / 60, the pendulum, the falls and the ticks read the same clock and never drift apart, even if you drag the weight halfway through a fall.
  • The timeline repeats: if the whole cycle had an odd number of beats, the next time round the rod would start from the wrong side with a jump. If the words add up to an odd total, one empty beat is added at the end.
  • On the second round the syllables of the first part of every word no longer fell and those of the round before stayed on the line, on top of each other: the hit given to the neighbouring syllables used overwrite: true, which kills every tween of that object, the timeline's ones included (the fall and the fade), and a repeating timeline cannot wind back a killed tween. Now what the landing moves (weight, width, squash, the line giving) lives in an object of its own, and the hit uses overwrite: 'auto', which only takes away the property that clashes.
  • The marks at the ends of the arc sat exactly on the rod's line: at the moment of the tick they looked like a broken-off piece of rod. Now the arc and its marks sit three degrees beyond the swing.
  • At fast tempos the whole word stayed on the line for a breath before leaving (at 208 BPM a beat lasts 0.29 seconds): the exit now starts 1.6 beats before the next word instead of 1.9, and the new word's small marks appear under the line while the old one fades, without touching it.

Libraries

GSAP 3.15.0, Archivo (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 animations