Skip to content
animorio
IT
All components

The ribbon microphone button

Buttons, Physics, TextCanvas, GSAPAdvancedCompressed weight: Demo 11 KBGSAP 28 KBFreeDownload the zip

A podcast's Subscribe button made as the head of an old ribbon microphone lying on its side: a chrome body, a grille of fine bars and behind it the pleated aluminium ribbon. Pressed, the word is spoken into the microphone: the sound runs along the ribbon, which draws the word's own waveform, and shakes the bars one by one; the letters swell as they are said, the ON AIR lamp warms up and lights, and the d of Subscribed grows in right when it is heard.

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 ribbon microphone button</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the Subscribe button of a podcast, made as the head of an old ribbon microphone lying on its side: a chrome
         body, a grille of fine chrome bars and, behind them, the corrugated ribbon. Pressed, the word is spoken into
         it: the sound runs out along the ribbon and shakes the bars, the letters swell as they are said, the ON AIR
         lamp lights and the missing letters of Subscribed grow in -->
    <div class="mic-wrap" data-wrap>
      <button class="mic" type="button" aria-pressed="false" aria-label="Subscribe to the podcast" data-mic data-autoclic>
        <canvas class="mic__grille" aria-hidden="true" data-grille></canvas>
        <span class="mic__shade" aria-hidden="true"></span>
        <span class="mic__lamp" aria-hidden="true">
          <span class="mic__glass mic__glass--warm" data-warm></span>
          <span class="mic__glass mic__glass--lit" data-lit></span>
          <span class="mic__onair mic__onair--dim" data-dim-text>ON AIR</span>
          <span class="mic__onair mic__onair--lit" data-lit-text></span>
        </span>
        <span class="mic__plate" aria-hidden="true" data-plate>
          <span class="mic__word" data-word>Subscribe</span>
        </span>
      </button>
      <p class="sr" aria-live="polite" data-live></p>
    </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.

26 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 ribbon microphone button” from Animorio and fit it into my site

What it does

On a black background a pill of polished chrome 60 pixels tall: inside, a grille of close vertical chrome bars, behind them two dark bands (the magnet's pole pieces) and between them a thin pleated aluminium ribbon running from end to end. In the left end there is a rectangular lamp that says ON AIR, unlit: very dark red glass and letters barely showing. In the middle of what is left there is a black bakelite plate with a chrome rim and the word Subscribe. With the mouse over it, a soft glint follows the pointer along the bars, and drawn quickly across them the bars are plucked like strings and quiver. Pressing it, the pill gives a little and springs back, and the word is spoken into the microphone: the sound comes out from under the plate and runs along the ribbon to both ends, so the ribbon draws the word's waveform, the hiss of the s, the round wave of the vowels, the snap of the b. Where it passes the bars bend and ring on a little, and the ones bending towards the light shine. On the plate each letter swells, heavier and wider, at the moment it is said. Meanwhile the ON AIR lamp warms up like a filament, a first glow, a moment's hesitation, then full red with pale letters, and its red is reflected on the bars beside it. At the end of the word the d of Subscribed grows out of nothing with a little bounce, right as it is heard. Pressing again, the lamp goes out through an amber glow, the small knock of a switch runs along the ribbon and the d folds away.

How it works

The voice spelled from the letters

The waveform is not recorded: the spell() function builds it from the letters of DONE. Each vowel becomes a stretch of voiced wave with its own pitch (the a lowest, the i highest) and three harmonics; s, f, h, z, x and a soft c a hiss of smooth noise (a hash at whole steps, joined with smoothstep); b, d, g, k, p, t and a hard c a moment of silence and then a snap that dies fast; l, m, n, v, w a softer vowel and the r rolled, its loudness trembling 26 times a second. A silent e after a consonant is short and soft. Each stretch has its envelope, and sig(voice, t) gives the wave's value at any moment.

The ribbon, a travelling wave

The ribbon is drawn on a canvas one column of pixels at a time. The column at a distance d from the plate shows the voice as it was d / SPEED seconds before: so the word comes out from under the plate and runs to both ends, and reads on the ribbon as on an oscilloscope. The pleats are alternate light and dark columns, and the slope of the wave lightens or darkens them like slats tilting towards the light; the columns end up in nine Path2D paths, one per tone, filled one at a time.

The bars, damped springs

Every bar of the grille is a string held at both ends, drawn with a quadratic curve: the middle point is its displacement. The displacement is a damped harmonic oscillator (frequency RING, damping DAMP) driven by the same wave that reaches the ribbon under it, stepped in 1/240 of a second with the frame capped at 1/30. The bars are split into three paths by the way they bend, each with its own chrome gradient: those bent towards the light shine, the others go dull.

The light on the chrome

Over the bars, in «lighter» mode, the same path is stroked again with a white radial gradient centred on the pointer (the glint) and a red one centred on the lamp, as strong as the lamp is lit. The pointer passing over the bars plucks them: those between its last position and the new one get a speed in proportion to the pointer's speed.

The letters and the lamp

The word on the plate is split into letters, each with the wght and wdth axes of the Anybody variable font in its CSS variables: every frame each letter takes its weight and width from the envelope of its stretch of voice. The letters Subscribed has in addition grow from zero width with back.out at the moment of their sound, and the plate is as wide as the longer word from the start, so it never jumps. The lamp is a GSAP timeline over two layers of glass: a first glow, a dip, then up to full in WARMUP seconds; going out, the red gives way to an amber glass that fades more slowly.

Values to change

NameFileDefaultWhat it changes
DONEscript.jsSubscribedThe word once subscribed: the letters it shares with the plate stay, the others grow in as they are said. It is also the word the ribbon draws.
TALKscript.js1How slowly the word is said: 1 = about a second, 2 = twice as long.
SPEEDscript.js230How fast the sound runs along the ribbon, in pixels per second.
LOUDscript.js1How hard the voice moves the ribbon and shakes the bars: 0 not at all.
BARSscript.js3.2The spacing of the grille's bars, in pixels.
RINGscript.js9How many times a second a bar swings on its own.
DAMPscript.js0.09How quickly a bar stops ringing: small rings long.
PLUCKscript.js1How much a pointer drawn across the grille plucks the bars: 0 not at all.
WARMUPscript.js0.22The seconds the ON AIR lamp takes to warm up and light fully.

Try them in the Playground

When to use it

For subscribing to a podcast, an online radio, a live show or a channel of interviews: wherever the voice is the product. The big moment lasts a second and dies down on its own; once on, the ON AIR lamp tells at a glance that you are subscribed.

On phones

The pill is 60 pixels tall and 336 wide, or the screen less 16 pixels a side: at 390 pixels it fits whole. At a touch it gives and the word is spoken as with the mouse; the glint shows under the finger, and dragging the finger along the grille plucks the bars as the mouse does. A second tap unsubscribes.

With reduced motion

Nothing moves: the ribbon and the bars stay still, the letters do not swell, the pill does not give. Pressing it, the ON AIR lamp lights with a fade and the d of Subscribed fades in; unsubscribing, the lamp goes out the same way.

Pitfalls

  • The white glint on bars that were already bright did not show: now it is centred halfway up, where the chrome is darker, and a little light falls on the dark between the bars too.
  • The first pluck was too weak, the bars moved half a pixel and looked still: the push is almost three times as strong, and the drawn displacement is softened with a hyperbolic tangent, so a bar plucked hard never crosses its neighbours.
  • The ribbon was a thin pale thread and the word's wave read badly: it is thicker, goes further up and down (the pole pieces are thinner to make room) and where it moves it throws a little light on the dark behind it.
  • The lamp's red covered a third of the grille and looked like a fault: its reach went down from 120 to 95 pixels on the bars and to 90 on the background.
  • Growing letters cannot be animated from width auto: the real width is measured first by letting it go for an instant, then animated in pixels and set back to auto at the end, or a letter swelled by the voice would be cut off. The plate is as wide as the longer word from the start, measured with an invisible copy, so it does not jump when the d arrives.
  • With a high LOUD the ribbon left its slot and ran over the pole pieces: its displacement is kept to the room between the two dark bands.

Libraries

GSAP 3.15.0, Anybody (font variabile, con gli assi del peso e della larghezza) 5.3.0.

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

Testing

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