Skip to content
animorio
IT
All components

The liquid glass tab bar

Navigation, WebGL, Physics, HoverWebGL, GSAPAdvancedCompressed weight: Demo 11 KBGSAP 28 KBFreeDownload the zip

The bottom bar of an app, Home, Search, Library and Profile, in frosted glass over a strip of abstract album covers drifting slowly behind it. The chosen tab sits under a lens of clear liquid glass: changing tab, the lens glides on a spring and stretches with its speed into a drop, round at the front and thin at the back, then settles with a wobble; all the way it really refracts what is under it, magnifying the icon and bending the covers, with the rainbow of chromatic aberration on its rim. It can be dragged with a finger too: held it swells, let go it picks the nearest tab.

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 liquid glass 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 an app, in frosted glass, over a strip of album covers that drifts slowly behind it. The tab
         you are on sits under a lens of clear liquid glass: going to another tab, the lens glides there, stretching
         into a drop as it speeds up, magnifying and bending the icons and the covers under it. It can be dragged
         with a finger and let go: it picks the nearest tab. Covers, bar, icons and lens are all drawn in one WebGL
         canvas; the links on top are the real, clear, navigation. The icons below are read by the script -->
    <div class="tabbar" data-tabbar>
      <canvas class="tabbar__scene" aria-hidden="true" data-canvas></canvas>
      <nav class="tabbar__nav" aria-label="Main" data-nav>
        <a class="tabbar__tab" href="#home" data-tab data-autoclic>
          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 10.5 12 4l8 6.5V19a1 1 0 0 1-1 1h-4.5v-5.5h-5V20H5a1 1 0 0 1-1-1z"/></svg>
          <span>Home</span>
        </a>
        <a class="tabbar__tab" href="#search" data-tab data-autoclic>
          <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>Search</span>
        </a>
        <a class="tabbar__tab" href="#library" aria-current="page" data-tab data-autoclic>
          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4.5v15M9.5 4.5v15M13.6 5.3l4.8 14.2"/></svg>
          <span>Library</span>
        </a>
        <a class="tabbar__tab" href="#profile" data-tab data-autoclic>
          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a4 4 0 1 0 0-8a4 4 0 0 0 0 8zM4.5 20c.9-3.7 3.8-5.5 7.5-5.5s6.6 1.8 7.5 5.5"/></svg>
          <span>Profile</span>
        </a>
      </nav>
      <p class="sr" aria-live="polite" data-live></p>
    </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.

18 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 liquid glass tab bar” from Animorio and fit it into my site

What it does

On a black background a row of brightly coloured square covers with abstract designs (a banded half sun, diagonal stripes, a triangle, waves, a crescent, slabs, arcs, a tilted checker) drifts slowly to the left and fades at both ends. Over its lower part floats a pill-shaped bar of dark frosted glass, with a thread of light along its top edge and a soft shadow on the covers: inside, blurred, the same covers pass by, and over them are four icons with their words, Home, Search, Library and Profile, in grey. Library sits under a lens of clear glass with a bright rim on the side of the light: inside, the icon and the word are bigger and light blue, and at the rim the glass bends the covers and splits the colours into a faint rainbow. Choosing another tab the lens runs there on a spring: setting off it stretches into a drop, full at the front and thin at the back, and everything it crosses swells and bends inside it; arriving the drop shortens, overshoots a touch and settles back into a pill, and the icon under it turns light blue while the one left turns grey again. With the mouse, the tab under the pointer brightens. Taking the lens with a finger or the mouse and dragging it, it lifts and swells past the edges of the bar and follows the hand, stretching with its speed; let go, it goes to the nearest tab. The right and left arrows, Home and End move the choice from the keyboard.

How it works

One WebGL canvas, two passes

First pass, into a texture the size of the canvas: the covers (a strip painted once in a 2D canvas and read with fract, so it drifts forever), the bar as a signed distance rounded rectangle, its shadow, the frosted glass and the icons. Second pass, on the screen: that texture, bent inside the lens. So the lens bends the icons and the frosted glass too, not just the background.

Frosted glass without blurring every frame

The bar's glass blurs nothing in real time: it reads a second copy of the strip, blurred once by the canvas (filter blur, repeated at the sides so the blur wraps round the ends too; where filter is missing, a copy at an eighth of the size softened by the linear filter), five times round the point, and darkens it with the glass colour. A thread of light follows the edge, stronger at the top.

The lens as a distance field

The lens is an uneven capsule (two circles of different radii and the lines touching both, from Inigo Quilez's formula), turned the way it is going. The length between the two centres and the two radii come from springs: still it is a pill; fast it stretches, the front radius shrinks a little and the back one more, so it becomes a drop. Near the ends of the bar it stretches less, so it never pokes out.

Refraction from the rim

The normal comes from the field itself, with four nearby reads. Inside the lens a domed profile (flat in the middle, steeper and steeper towards the rim, like a quarter circle) says how far the glass reaches out for what lies beyond the rim, along the normal; the middle magnifies by ZOOM. Red, green and blue are read at three different distances (PRISM): at the rim the colours split. On top, a thread of light on the side of the light, a weaker one on the other, a soft gloss and a dark ring just outside.

The springs and the drop

The lens's position is a spring towards the chosen tab (SPRING), integrated in steps of 1/240 of a second with the frame's step capped at 1/30. The stretch chases the speed on a second, livelier spring, so on arrival the drop shortens past its shape and wobbles. Dragging, the position spring stiffens onto the finger and a third spring lifts and swells the lens; let go, it picks the nearest tab. The icons take the chosen colour in proportion to how close the lens is.

Values to change

NameFileDefaultWhat it changes
DRIFTscript.js16How fast the covers drift behind the bar, in pixels a second.
SPRINGscript.js[300, 22]The spring the lens glides on: stiffness, and damping (lower, more it overshoots).
STRETCHscript.js0.55How much the lens stretches into a drop with its speed.
BENDscript.js16How far the rim of the lens reaches out for what lies outside it, in pixels.
BEVELscript.js18How wide the rounded rim of the lens is, in pixels.
ZOOMscript.js0.22How much the middle of the lens magnifies.
PRISMscript.js0.28How far apart red and blue bend on the rim: the rainbow.

Try them in the Playground

When to use it

For the bottom navigation bar of an app or a phone-first site, especially where colourful content scrolls under the bar: music, photos, video, a shop. From three to five tabs; the strip of covers is part of the demo and is replaced with the app's real content painted into the same texture.

On phones

The bar takes the width of the screen minus 32 pixels and the tabs share the room; the canvas draws at density 2. A tap on a tab sends the lens there, and the finger can drag it along the bar (touch-action: pan-y, so vertically the page still scrolls); the mouse hover that brightens a tab does not exist on a phone.

With reduced motion

The covers stand still and the canvas is redrawn only when something changes. The lens does not travel or stretch: it fades out where it was and reappears on the new tab; dragged, it follows the finger without swelling or stretching.

Pitfalls

  • In GLSL a uniform and a function cannot share a name: the function reading the strip was called like the strip uniform and the shader did not compile.
  • Blurring the covers every frame for the frosted glass cost too much with WebGL in software: a copy blurred once is read instead, and the canvas blur is repeated at the sides so the strip, which wraps, shows no seam.
  • The copy at an eighth of the size, softened only by the linear filter, showed a grid of little squares in the glass: it is used only where the canvas cannot blur.
  • Dragging a link with the mouse started the browser's own drag and cancelled the lens's: the links have draggable false and dragstart is blocked.
  • The stretched drop, arriving at a tab at the end of the bar, poked out of it: near the ends the stretch is limited to the room left.
  • With the uneven capsule formula, if the two centres coincide and the radii differ it divides by zero: the distance between the centres never goes below the difference of the radii.

Libraries

GSAP 3.15.0, Figtree (font variabile) 5.3.0.

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

Testing

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