
The inchworm menu
Menus, Hover, Transitions
NewFree
A bar with three menus sharing a single panel: going from one menu to the next the panel changes width, height and place, its little arrow slides under the new button and the lists slide in from the side they come from, always cut inside the panel.
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 dropdown that changes shape</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/plus-jakarta-sans@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<div class="zone" data-zone>
<!-- one panel for every menu: moving from one to the next it changes size and place, and the contents slide in
from the side they come from. Each list sits in the page right after its button, for the Tab key -->
<nav class="nav" aria-label="Main" data-nav>
<ul class="nav__list">
<li>
<button class="nav__trigger" type="button" aria-expanded="false" aria-controls="drop-products" data-trigger data-autoclic>Products<svg class="nav__caret" viewBox="0 0 14 14" aria-hidden="true"><path d="M3.5 5.5 7 9l3.5-3.5"/></svg></button>
<div class="drop drop--products" id="drop-products" data-section>
<ul class="drop__list">
<li><a class="drop__link" href="#"><span class="drop__icon" style="--tint: #ece8ff; --mark: #6246ea"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 19V11M12 19V5M19 19v-5"/></svg></span><span class="drop__text"><b>Analytics</b><small>See what happens on your site</small></span></a></li>
<li><a class="drop__link" href="#"><span class="drop__icon" style="--tint: #dff6ec; --mark: #138a5a"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M17 3l3 3-3 3M20 6H9a5 5 0 0 0-5 5M7 21l-3-3 3-3M4 18h11a5 5 0 0 0 5-5"/></svg></span><span class="drop__text"><b>Automations</b><small>Let the routine run by itself</small></span></a></li>
<li><a class="drop__link" href="#"><span class="drop__icon" style="--tint: #ffeedd; --mark: #d0611b"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 3h7l4 4v14H7zM14 3v4h4M10 12h5M10 16h5"/></svg></span><span class="drop__text"><b>Reports</b><small>Numbers your team can read</small></span></a></li>
</ul>
</div>
</li>
<li>
<button class="nav__trigger" type="button" aria-expanded="false" aria-controls="drop-solutions" data-trigger data-autoclic>Solutions<svg class="nav__caret" viewBox="0 0 14 14" aria-hidden="true"><path d="M3.5 5.5 7 9l3.5-3.5"/></svg></button>
<div class="drop drop--solutions" id="drop-solutions" data-section>
<div class="drop__column">
<p class="drop__heading">By size</p>
<a class="drop__plain" href="#">Startups</a>
<a class="drop__plain" href="#">Agencies</a>
<a class="drop__plain" href="#">Enterprise</a>
</div>
<div class="drop__column">
<p class="drop__heading">By field</p>
<a class="drop__plain" href="#">Retail</a>
<a class="drop__plain" href="#">Education</a>
<a class="drop__plain" href="#">Nonprofits</a>
</div>
</div>
</li>
<li>
<button class="nav__trigger" type="button" aria-expanded="false" aria-controls="drop-developers" data-trigger data-autoclic>Developers<svg class="nav__caret" viewBox="0 0 14 14" aria-hidden="true"><path d="M3.5 5.5 7 9l3.5-3.5"/></svg></button>
<div class="drop drop--developers" id="drop-developers" data-section>
<a class="drop__card" href="#">
<svg class="drop__glyph" viewBox="0 0 24 24" aria-hidden="true"><path d="M8 8l-4 4 4 4M16 8l4 4-4 4M13.5 5l-3 14"/></svg>
<b>Read the docs</b>
<small>Everything you need to build with us, from the first call to the last.</small>
</a>
<ul class="drop__list drop__list--small">
<li><a class="drop__link drop__link--small" href="#"><span class="drop__mini"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h16M4 12h16M4 18h10"/></svg></span><b>API reference</b></a></li>
<li><a class="drop__link drop__link--small" href="#"><span class="drop__mini"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h10l4 4v12H5zM9 12h6M9 16h4"/></svg></span><b>Guides</b></a></li>
<li><a class="drop__link drop__link--small" href="#"><span class="drop__mini"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 7v5l3 2M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z"/></svg></span><b>Changelog</b></a></li>
<li><a class="drop__link drop__link--small" href="#"><span class="drop__mini"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 12h4l3-7 4 14 3-7h4"/></svg></span><b>Status</b></a></li>
</ul>
</div>
</li>
<li><a class="nav__trigger nav__trigger--link" href="#">Pricing</a></li>
</ul>
<!-- the white panel behind the lists, and its little arrow: they move, the lists take turns on top -->
<span class="panel" data-panel aria-hidden="true"></span>
<span class="arrow" data-arrow aria-hidden="true"></span>
</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>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.
40 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The dropdown that changes shape” from Animorio and fit it into my siteThe panel is a single element behind the lists. GSAP takes its x, width and height to those of the list to show, measured each time with offsetWidth and offsetHeight, in MORPH seconds with expo.out. The list goes under its button, kept inside the window, and the little arrow under the button but at least 26 pixels from the panel’s corners.
The direction comes from comparing the new menu with the old one: the old list moves SLIDE pixels towards the opposite side and vanishes in 0.18 seconds, the new one arrives from SLIDE pixels on the other side in 0.45 seconds with power3.out.
On every update each visible list gets a clip-path inset worked out from where it and the panel are at that moment: while the panel changes shape, nothing sticks out of its edges.
In the code each list sits right after its button: so the Tab key goes from the button into its list and then to the next button. The hidden lists have visibility: hidden and stay out of the way.
The pointer opens by going over a button, and with the mouse a click only opens; a finger, the keyboard or a script open and close. Once the pointer leaves, closing waits GRACE seconds; the bridge is an ::after of the bar as tall as the space between bar and panel (GAP).
| Name | File | Default | What it changes |
|---|---|---|---|
MORPH | script.js | 0.5 | The seconds of the panel changing size and place. |
SLIDE | script.js | 36 | The pixels the lists slide when going from one menu to another. |
LIFT | script.js | 10 | The pixels the panel rises from when it opens. |
GRACE | script.js | 0.2 | The seconds the panel waits, after the pointer leaves, before closing. |
GAP | script.js | 12 | The pixels between the bar and the panel. |
For the navigation of a site with rich menus (products, solutions, documentation) where each menu holds something different. For a single menu a plain dropdown is enough.
The buttons tighten to fit a 390 pixel screen; a tap opens and closes, the panel stays inside the screen, and the columns of Solutions and the card of Developers stack one under the other.
The panel does not travel and the lists do not slide: changing menu is a quick fade, and so are opening and closing.
GSAP 3.15.0, Plus Jakarta Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.3 KB; the libraries: GSAP 28 KB.
Tested on 2 October 2026
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.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.