
The send button
Buttons, Transitions, SVG
NewFree
A dark navigation bar with a notch in its edge and a coral disc floating in it: choosing a tab, notch and disc slide there on a spring, the notch widens as it runs, the disc dips and squashes like a drop, and the icon rises into the disc with its own little move.
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 notched tab bar</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/lexend@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the tab bar: a dark bar with a notch cut in its top edge and a coral disc floating in it. Choosing a tab, the
notch and the disc slide there on a spring (the notch widens while it runs, the disc dips and squashes),
the old icon drops back into the bar and the new one rises into the disc. The bar's shape is drawn by the
script -->
<nav class="bar" aria-label="Main" data-bar>
<svg class="bar__shape" aria-hidden="true" data-shape><path data-path/></svg>
<span class="bar__bubble" aria-hidden="true" data-bubble></span>
<span class="bar__label" aria-hidden="true" data-label></span>
<button class="tab" type="button" data-tab="Home" data-autoclic>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 11.2 12 4.8l8 6.4V20h-5.6v-5.6H9.6V20H4z"/></svg>
<span class="sr">Home</span>
</button>
<button class="tab" type="button" data-tab="Search">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M10.5 4.5a6 6 0 1 0 0 12a6 6 0 1 0 0-12zM15 15l4.5 4.5"/></svg>
<span class="sr">Search</span>
</button>
<button class="tab" type="button" data-tab="New">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
<span class="sr">New</span>
</button>
<button class="tab" type="button" data-tab="Saved">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 19.5s-7.5-4.6-7.5-10A4.2 4.2 0 0 1 12 7a4.2 4.2 0 0 1 7.5 2.5c0 5.4-7.5 10-7.5 10z"/></svg>
<span class="sr">Saved</span>
</button>
<button class="tab" type="button" data-tab="Profile">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4.5a3.6 3.6 0 1 0 0 7.2a3.6 3.6 0 1 0 0-7.2zM5 19.5c.8-3.4 3.6-5.5 7-5.5s6.2 2.1 7 5.5"/></svg>
<span class="sr">Profile</span>
</button>
</nav>
</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.
18 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 notched tab bar” from Animorio and fit it into my siteThe bar is an SVG path the script redraws on every frame: a rectangle with rounded ends and, around the point c, a notch made of two Bézier curves. Half its width is NOTCH[0] plus the speed times STRETCH, and it never cuts into the rounded corners.
The point c follows the chosen tab on a hand-written spring (SPRING), worked out on GSAP’s ticker in steps of 4 milliseconds. Its speed gives the notch’s width, how far the disc sinks into the bar (DIP) and how much it squashes: wider and lower by the same amount.
The previous icon sinks back to y 0 with power3.inOut; the new one rises by RISE pixels with back.out, after a delay that grows with the distance between the two tabs, so it arrives together with the disc. Once there it does its move (MOVES), on the icon and not on the button, so it does not fight the rise.
Under the disc there is a single name that follows c on every frame: on a new choice it fades out dropping slightly, changes its text and comes back.
The tabs are buttons in a nav, and the chosen one has aria-current="page"; the arrows move the focus between the tabs, Home and End go to the ends. The library’s preview clicks the data-autoclic mark, which the script moves to the next tab every time.
| Name | File | Default | What it changes |
|---|---|---|---|
START | script.js | 0 | The tab chosen when the page opens (0 is the first). |
SPRING | script.js | [210, 0.62] | The spring of the notch and the disc: how stiff it is and how much it is held back. |
NOTCH | script.js | [42, 34] | The notch at rest: half its width and its depth, in pixels. |
STRETCH | script.js | 0.03 | How much the notch widens with its speed. |
DIP | script.js | 0.012 | How far the disc dips into the bar with its speed. |
RISE | script.js | 40 | How far an icon rises into the disc, in pixels. |
For the navigation at the bottom of the screen in a web app or a phone-first site, for an app’s sections, for a toolbar.
The bar takes the width of the screen minus a margin and the tabs move closer; next to the ends the notch narrows so as not to cut into the rounded corners. Two quick taps do not zoom the page.
Notch, disc and icons go straight to their places: no slide, no drop, no icon moves and no entrance.
GSAP 3.15.0, Lexend (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 4.8 KB; the libraries: GSAP 28 KB.
Tested on 3 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.