Skip to content
animorio
IT
All components

The isobar menu

Menus, Hover, TextCanvas, GSAP, CSS onlyAdvancedCompressed weight: Demo 8.2 KBGSAP 28 KBFreeDownload the zip

In the minimal style, on black: the menu of a weather app. Behind the links lies an invisible pressure field, drawn as hairline isobars recalculated every frame. The link under the pointer becomes a low: the isobars tighten round it in rings, drift slowly in towards it and take the accent colour, and its pressure reading drops on the right. Opening, the lines are drawn out from the middle in a widening circle.

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 isobar menu</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the menu of a weather app. Behind the links an invisible pressure field is drawn as hairline isobars. The link
         under the pointer becomes a low: the isobars tighten round it in rings, drift in towards it and light up, its
         pressure reading drops; the others relax. Opening, the isobars are drawn out from the middle -->
    <div class="isobar" data-frame>
      <canvas class="field" aria-hidden="true" data-canvas></canvas>

      <button class="toggle" type="button" aria-expanded="false" aria-controls="isobar-menu" data-toggle data-autoclic>
        <span class="toggle__icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" data-icon>
            <path class="toggle__iso" data-iso="0" d="M3 9.5 C7 6, 11 13, 15 9.5 S21 7, 21 7"/>
            <path class="toggle__iso" data-iso="1" d="M3 14.5 C7 11, 11 18, 15 14.5 S21 12, 21 12"/>
          </svg>
        </span>
        <span class="toggle__words" aria-hidden="true">
          <span class="toggle__word" data-word-open>Menu</span>
          <span class="toggle__word" data-word-close>Close</span>
        </span>
        <span class="sr" data-toggle-name>Open the menu</span>
      </button>

      <p class="brand" aria-hidden="true" data-brand>Cirrus weather</p>

      <nav class="menu" id="isobar-menu" aria-label="Main" data-menu inert>
        <ul class="menu__list">
          <li><a class="row" href="#today" aria-current="page" data-row><span class="row__mask"><span class="row__word" data-word>Today</span></span><span class="row__read" data-read>1013 hPa</span></a></li>
          <li><a class="row" href="#radar" data-row><span class="row__mask"><span class="row__word" data-word>Radar</span></span><span class="row__read" data-read>1013 hPa</span></a></li>
          <li><a class="row" href="#forecast" data-row><span class="row__mask"><span class="row__word" data-word>Forecast</span></span><span class="row__read" data-read>1013 hPa</span></a></li>
          <li><a class="row" href="#maps" data-row><span class="row__mask"><span class="row__word" data-word>Maps</span></span><span class="row__read" data-read>1013 hPa</span></a></li>
          <li><a class="row" href="#alerts" data-row><span class="row__mask"><span class="row__word" data-word>Alerts</span></span><span class="row__read" data-read>1013 hPa</span></a></li>
        </ul>
      </nav>
    </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.

30 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 isobar menu” from Animorio and fit it into my site

What it does

On a black background there is only a pill button with a thin outline: inside, two small wavy isobars drawn in line and the word Menu; on the right, small, the app’s name, Cirrus weather. Pressed, Menu goes up and Close comes in its place, the button’s two isobars spring apart, and a circle widens from the middle with the isobars appearing inside it: dozens of very thin white lines, almost horizontal, swaying slowly because two invisible swells of the field wander very slowly. The five links rise one after the other from their masks, Today, Radar, Forecast, Maps and Alerts, each with its pressure on the right, 1013 hPa. Beside the current page’s link the isobars already make a small dip. Moving the mouse over the links, the one under the pointer becomes a low on a spring, just after the word, like the L beside its name on a weather map: the lines crowd round it in tighter and thicker rings that drift slowly in towards the middle as if the wind pulled them in, the closest ones light up vermilion, the word takes weight and width and its pressure drops to 986 hPa, written in vermilion. The other links relax back to the slope. The pointer on its own bends the lines a little wherever it goes. Clicking a link its dip deepens once more for a moment, then the menu closes: the links sink from the last one, the circle of isobars withdraws to the middle and Close turns back into Menu, the button’s two isobars bouncing back into place.

How it works

A pressure field

The pressure at each point is a sum: a light slope from top to bottom, two slow waves that wander with time, and a Gaussian dip for each link, DEPTH deep times its strength and SPREAD rows wide. The pointer adds a small, narrower dip. Nothing is drawn by hand: every line comes from this formula.

Isobars with marching squares

Every frame the pressure is worked out on the nodes of a 5 pixel grid; for each level, RINGS apart, each cell tells which side the line enters and leaves by, and the exact point on the side is found by interpolation. They are short segments that, in a row, make smooth curves. The segments are gathered into a few groups by thickness and colour, so each frame has only seven brush strokes.

Rings drifting in

The levels don’t stand still: every second they drop by FLOW steps, so every ring round a dip slowly tightens towards the middle and a new one is born outside, like wind lines being drawn in. A line’s thickness and light grow with how much dip is felt at that point.

The dips’ spring

Each link has its strength, heading for 1 if the pointer is on it, for 0.22 if it is the current page and for 0 otherwise, on a spring (SPRING) with a push at each change: the dip goes a little too far and settles. The strength also drives Mona Sans weight and width and the pressure written on the right, 1013 less 27 times the strength. The rings within 1.35 times the dip’s width take the accent, fading with distance.

Opening, closing, keys

One GSAP timeline: Menu and Close swap, the isobars appear inside a circle widening from the middle in 1.4 seconds, the links rise out of their masks 50 milliseconds apart. Closing, the circle withdraws and the button’s isobars come back on an elastic.out. The button has aria-expanded, the closed menu is inert, the arrows move the dip, Esc closes, Tab goes round the button and the links. The preview’s click (detail 0) makes a whole tour.

Values to change

NameFileDefaultWhat it changes
DEPTHscript.js1.1How deep the dip under the pointer is: the deeper, the tighter the isobars crowd round the link.
SPREADscript.js0.85How wide a dip is, in rows.
RINGSscript.js0.12The pressure step between two isobars (less, more lines).
FLOWscript.js0.035How fast the rings drift in towards the dip (0, they stand still).
SPRINGscript.js[150, 13]The dips’ spring: how stiff and how much it is held back.
WEIGHTscript.js[300, 640]The weight of a quiet link and of the one under the pointer.
WIDTHscript.js[90, 112]The width of a quiet link and of the one under the pointer.
STAGGERscript.js0.05The seconds between one link and the next when opening and closing.

Try them in the Playground

When to use it

For the menu of a weather app or site, a weather station, a service for sailing, flying or mountains, or a studio that works with data. It suits black with four, five or six short links; the reading on the right can show a real number for each section.

On phones

The frame is as wide as the screen less 32 pixels and at most 88% of the height tall; the links shrink with the width and the height, and below 340 pixels the app’s name is left out. The dip follows a finger sliding over the links, like the mouse, and a tap chooses the link.

With reduced motion

The field stays still: no wandering waves, no drifting rings, no springs. The isobars and the links fade in, and the dip moves from link to link at once, with the same tighter lines and the same accent.

Pitfalls

  • With marching squares the saddle cells (cases 5 and 10) have two segments: both must be drawn, or the isobars break exactly where two dips meet.
  • One brush stroke per segment means thousands of stroke() calls a frame: the segments are grouped by thickness and colour and drawn in a single path per group.
  • The field’s frame is 24 pixels bigger than the menu on each side and fades out with a radial mask: without it the isobars end abruptly at the edge and the menu looks like a window.

Libraries

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

Compressed with gzip, the three demo files weigh 8.2 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