Skip to content
animorio
IT
All components

The living icons tab bar

Navigation, SVG, PhysicsGSAPAdvancedCompressed weight: Demo 8.2 KBGSAP 28 KBFreeDownload the zip

An app's bottom tab bar with five icons drawn as strokes: choosing one, it redraws itself in colour over the grey one and does its move (the house sends up smoke and opens its door, the lens sweeps a circle, the bell swings with its clapper, the profile nods, the plus turns into an X), while the pill slides across stretching and the label rises.

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 living icons tab bar</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/figtree@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the tab bar of a phone app: five icons drawn as SVG strokes. Each one, chosen, plays its own little move: the
         house puffs smoke from its chimney, the lens sweeps a circle, the bell rings, the head nods, the plus turns
         into a cross. The strokes are redrawn by the script on every frame; the label and the pill move from one tab
         to the next -->
    <nav class="bar" aria-label="Main" data-bar>
      <span class="bar__pill" data-pill aria-hidden="true"></span>
      <button class="tab" type="button" data-tab="home" data-autoclic>
        <svg class="tab__icon" viewBox="0 0 28 28" aria-hidden="true" data-icon></svg>
        <span class="tab__label">Home</span>
      </button>
      <button class="tab" type="button" data-tab="search" data-autoclic>
        <svg class="tab__icon" viewBox="0 0 28 28" aria-hidden="true" data-icon></svg>
        <span class="tab__label">Search</span>
      </button>
      <button class="tab" type="button" data-tab="add" data-autoclic>
        <svg class="tab__icon" viewBox="0 0 28 28" aria-hidden="true" data-icon></svg>
        <span class="tab__label">New</span>
      </button>
      <button class="tab" type="button" data-tab="bell" data-autoclic>
        <svg class="tab__icon" viewBox="0 0 28 28" aria-hidden="true" data-icon></svg>
        <span class="tab__label">Alerts</span>
        <span class="tab__dot" aria-hidden="true" data-dot>3</span>
      </button>
      <button class="tab" type="button" data-tab="profile" data-autoclic>
        <svg class="tab__icon" viewBox="0 0 28 28" aria-hidden="true" data-icon></svg>
        <span class="tab__label">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>

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.

20 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 living icons tab bar” from Animorio and fit it into my site

What it does

On a white background, alone in the middle, a white pill-shaped bar with a soft shadow and five icons in grey strokes: house, lens, plus, bell with a red 3, and profile. The chosen tab is tomato red, sits in a pink pill and has its name below. On arrival the bar rises from below, then the house redraws itself in red and does its move. Choosing another tab the pill slides over to it on a spring, stretching in the direction it runs like a drop; the previous icon loses its colour from its last stroke back and its name drops and fades, the new one redraws itself in red stroke by stroke over the grey one and does its move: the house squashes and bounces, its door opens on a yellow light and three wisps of smoke curl up from the chimney and fade; the lens sweeps a full circle leaning into the turn and a glint crosses its glass; the plus turns an eighth and becomes an X inside a frame that draws itself, and turns back into a plus when you go elsewhere; the bell swings on its hook with the clapper following late, and the 3 goes away; the profile nods twice with its shoulders rising. A little after leaving the bell a new alert arrives: a 1 pops up and the grey bell rings by itself.

How it works

Icons made of numbers

Each icon is a function that, from a few numbers, returns its strokes as SVG paths: the house from how far its door is open, how squashed it is and where the wisps of smoke are; the lens from how far it has gone round; the plus from how far it has turned and how long its arms are; the bell from the two angles of its pendulums; the profile from how far it nods. Every frame the paths are worked out again and written into the d attribute.

The colour that draws itself

Each icon is drawn twice with the same paths: grey underneath, in colour on top. The colour layer has pathLength="1" and stroke-dasharray, and a single number (from 0 to 1) says how much ink there is: each stroke gets its share, one after the other, so the icon redraws itself stroke by stroke and, the other way round, fades from its last stroke back. The smoke, the door's light, the glint and the plus's frame live only in the colour layer.

The moves

The moves are GSAP timelines on the icons' numbers (the door, the wisps of smoke, the lens's turn, the plus's rotation with back.out), scaled by PLAY. Not the bell: it is a hand-written pendulum, and the clapper is a second pendulum hanging inside it and pushed by its acceleration, so it follows late; a choice only gives it a knock, physics does the rest.

The drop-shaped pill

The pill follows the middle of the chosen tab on a spring (PILL), in 4 millisecond steps with the frame step capped at 1/30 of a second. From its speed come how much it stretches (STRETCH) and how much it flattens, and the stretch sits more in front than behind, like a running drop.

Bar and keyboard

The tabs are buttons in a nav and the chosen one has aria-current="page"; the arrows move from tab to tab, Home and End go to the ends. The library's preview clicks the tabs in turn: each has data-autoclic.

Values to change

NameFileDefaultWhat it changes
STARTscript.js0The tab chosen when the page opens (0 is the first).
DRAWscript.js0.5The seconds an icon takes to redraw itself in colour.
PLAYscript.js1How big the icons' moves are (0 still, 2 twice as much).
PILLscript.js[380, 0.62]The pill's spring: how stiff, and how much it is held back.
STRETCHscript.js0.0016How much the pill stretches with its speed.
BADGEscript.js3The number on the bell (0 hides it).

Try them in the Playground

When to use it

For the navigation bar of an app or a site made for phones, with four or five sections: wherever every tap can have its little reward and the icons can tell what lies behind them (a lived-in home, a search that searches, an alert that rings).

On phones

The bar is 360 pixels wide and on a phone narrows to the width of the screen; it keeps five equal tabs and each tab is a target of at least 60 pixels. At a touch the icon shrinks slightly, as with the mouse pressed, then does its move.

With reduced motion

The icons change colour at once and stay still: no moves, no smoke and no swinging; the pill jumps to the new tab without travelling, the label appears without rising, and the plus stays a plus.

Pitfalls

  • The plus's frame draws itself on its own: counted among the strokes that share the ink, the last arm of the cross stayed grey.
  • The profile's first nod turned the head round the neck: at 28 pixels it looked like a head sliding sideways. Now the head drops and gets shorter, as seen from the front while bending forward, and the shoulders rise.
  • The house's first door narrowed inside its frame, and that small it only seemed to shrink: now the frame stays, the free edge moves and a yellow light shows behind it.
  • The plus turned back into a plus by itself after a moment and the X hardly showed: it stays an X while the tab is chosen, and leaving it goes on to the next quarter turn, that is, back to a plus, even halfway through a turn.
  • The alert that arrives after leaving the bell must be booked after cancelling the old one: in the opposite order it was cancelled as soon as it was booked and never came.

Libraries

GSAP 3.15.0, Figtree (font variabile) 5.3.0.

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

Testing

Tested on 4 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: Done

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