Skip to content
animorio
IT
All components

The Chladni sand card

Cards, Physics, HoverGSAP, CanvasAdvancedCompressed weight: Demo 6.6 KBGSAP 28 KBFreeDownload the zip

The card of a bookshelf speaker, with a dark metal plate on top dusted with pale sand: when the speaker plays the plate vibrates, the sand jumps where the plate moves and stops where it stays still, and draws the figure of that sound, as on Ernst Chladni’s plates. Each sound profile, Warm, Balanced and Bright, is a different tone and a different figure: choosing one the sand runs across the plate from the old figure to the new one while the hertz count. With the pointer over the plate, or a click, the tone plays as long as you like.

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 Chladni sand card</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist-mono@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the card of a bookshelf speaker. On top of it a square metal plate with fine pale sand: when the speaker plays
         its tone the plate vibrates, the sand jumps where the plate moves and gathers where it stays still, and draws
         the shape of the sound (a Chladni figure). Each sound profile is a different tone and a different figure:
         choosing one, the sand runs across the plate into the new figure. With the pointer over the plate (or a press,
         or the keyboard) the tone plays and the sand dances. Thousands of grains, moved by the script on a canvas -->
    <article class="speaker" aria-labelledby="speaker-name" data-speaker>
      <button class="plate" type="button" aria-pressed="false" data-plate data-autoclic>
        <canvas class="plate__sand" aria-hidden="true" data-sand></canvas>
        <span class="plate__bolt" aria-hidden="true"></span>
        <span class="sr" data-plate-label>Play the tone</span>
      </button>
      <p class="meter" aria-hidden="true"><span class="meter__hz"><span data-hz>440</span> Hz</span><span class="meter__state" data-state>Hover to play</span></p>

      <div class="info">
        <div class="info__head">
          <div>
            <h2 class="info__name" id="speaker-name">Mora Two</h2>
            <p class="info__kind">Bookshelf speaker &middot; Walnut</p>
          </div>
          <p class="info__price">&euro;490</p>
        </div>
        <div class="profiles" role="radiogroup" aria-label="Sound profile" data-profiles></div>
      </div>
      <p class="sr" aria-live="polite" data-live></p>
    </article>
  </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.

33 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 Chladni sand card” from Animorio and fit it into my site

What it does

On a black background an almost black card 340 pixels wide, with a grey hairline and round corners. At the top a square plate of dark anodised metal, with a soft sheen and a bolt in the middle, dusted with seven thousand grains of pale sand. When the page opens the sand is scattered at random; then the speaker plays the Balanced tone and in three seconds the grains jump away from the parts that vibrate and gather in thin curved lines, the Chladni figure of that tone. Under the plate, in a monospaced face, 440 HZ in electric blue and on the right HOVER TO PLAY, which becomes PLAYING while the plate sounds. Then the name, Mora Two, Bookshelf speaker · Walnut, the price and three profiles in a thin track, Warm, Balanced and Bright, the chosen one in a blue pill that slides with a bounce. Choosing another profile the hertz count to the new one (180, 440, 1,200), the plate plays by itself for three seconds and the sand runs from the old figure to the new: Warm has a few wide curves, Bright a rose of arcs and a diagonal. With the pointer over the plate the tone plays and the sand moves as long as the pointer stays; a click leaves it playing until you click again.

How it works

The plate’s vibration

A square plate vibrating in one of its modes (n, m) has the shape cos(nπx)·cos(mπy) − cos(mπx)·cos(nπy), with x and y from 0 to 1. Where this function is zero the plate stands still: those are the nodal lines, the ones the sand draws. Each profile in PROFILES has its pair (n, m) and its hertz.

Each grain’s hop

At every frame each grain hops in a random direction, as far as the plate under it vibrates (JUMP times the absolute value of the function): where the plate moves a lot it hops far, on the nodal lines it hardly moves. So, by themselves, the grains come to rest where the plate is still.

The push towards the lines

With the hops alone the figure would take half a minute: each grain also gets a small push down the slope of the vibration’s square, f·∇f (PULL), which takes it to the nearest still place. The gradient is worked out exactly from the same functions; at the edges the grains bounce back in.

Seven thousand dots on a canvas

The grains are two Float32Arrays; at every frame a canvas at the screen’s density (2 at most) is cleared and each grain is a fillRect of GRAIN pixels. The strength of the vibration rises and falls softly (in a fifth and a third of a second) and when the plate is still the GSAP ticker lets go and nothing more is drawn.

Keyboard and touch

The plate is a button with aria-pressed: Enter, Space, a click or a tap keep the tone playing or stop it, and the mouse passing over plays it as long as it stays. The profiles are a radiogroup with the arrows, Home and End, and an aria-live says the profile and its hertz. The library preview’s click goes from one profile to the next.

Values to change

NameFileDefaultWhat it changes
PROFILESscript.js[{ name: 'Warm', hz: 180, n: 1, m: 4 }, …]The sound profiles: the name, the hertz written under the plate and the plate’s mode (n and m, two different numbers from 1 to 12: the higher they are, the finer the figure). Four at most.
STARTscript.js'Balanced'The profile chosen at the start (its name, as in PROFILES).
GRAINSscript.js7000How many grains of sand are on the plate.
JUMPscript.js0.011How far a grain hops where the plate vibrates most, as a fraction of the plate.
PULLscript.js1.4How strongly the grains drift towards the still lines (0 = only the hops, the figure comes much more slowly).
BURSTscript.js3How long the speaker plays by itself when a profile is chosen, in seconds.
GRAINscript.js1.25How big a grain is, in pixels.

Try them in the Playground

When to use it

For the card of a speaker, headphones, a turntable or an instrument in an electronics or music shop; also for an equaliser or the presets of an audio app, an electronic music festival or a science museum selling an object.

On phones

The card is 340 pixels wide, or the screen minus 32, and the canvas is redrawn at its real size and the screen’s density. There is no hover: a tap on the plate starts the tone and another stops it, and the label says TAP TO PLAY. The same grains and the same physics as on a computer.

With reduced motion

The sand never moves: when the page opens it is already in its figure (worked out before showing it) and choosing another profile the plate fades out and comes back with the new figure already drawn. The hertz change without counting.

Pitfalls

  • The labels on the plate (the hertz and the state) ended up under the grains and could not be read: they sit in a row under the plate.
  • With random hops alone the figure formed too slowly and was still blurred after three seconds: it needs the push along f·∇f, which takes each grain to the nearest still line.
  • The preview’s click would have switched the plate on and off in turn, always on the same figure: a script click (detail 0, no key pressed) moves to the next profile, so the preview shows all the figures.
  • At the saddle points, where two nodal lines cross, the plate is still around them too: there the sand stays in small clouds instead of lines. Real plates do the same and we left it.

Libraries

GSAP 3.15.0, Geist (font variabile) 5.3.0, Geist Mono (font variabile) 5.3.0.

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

Testing

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