Skip to content
animorio
IT
All components

The rewinding breadcrumbs

Navigation, Physics, TextGSAP, CSS onlyAdvancedCompressed weight: Demo 15 KBGSAP 28 KBFreeDownload the zip

The breadcrumbs of a file drive made like a tape measure: the path is the tape, and the yellow hook at its end pulls new folders out from under the last chevron. Choosing a folder higher up, the tape after it rewinds into its chevron, which opens like a mouth: the nearest letters spread apart and slip under first, and the hook comes home last with a clack.

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 rewinding breadcrumbs</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/albert-sans@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the breadcrumbs of a studio's file drive, made like a tape measure: the path is a tape and the yellow hook at
         its end pulls new folders out from under the last chevron. Going up, the tape rewinds into the chevron after
         the folder chosen, letter by letter, and the hook comes home last. Each letter is a weight on a string worked
         out on every frame; the chevrons are the slots the tape slips under -->
    <div class="frame" data-frame>
      <nav class="crumbs" aria-label="Breadcrumb" data-crumbs data-autoclic>
        <span class="crumbs__case" aria-hidden="true" data-case></span>
        <div class="crumbs__strip" data-strip>
          <ol class="crumbs__list" data-list>
            <li class="crumb crumb--root" data-id="files">
              <a class="crumb__link" href="#">
                <svg class="crumb__icon" viewBox="0 0 20 20" aria-hidden="true">
                  <path d="M5.5 4.5h9a2.5 2.5 0 0 1 2.5 2.5v6a2.5 2.5 0 0 1-2.5 2.5h-9A2.5 2.5 0 0 1 3 13V7a2.5 2.5 0 0 1 2.5-2.5z"/>
                  <path d="M3 10.6h14M12.6 13h1.8"/>
                </svg>
                <span class="crumb__name"><span class="crumb__text">Files</span></span>
              </a>
              <span class="crumb__sep" aria-hidden="true" data-sep>
                <svg viewBox="0 0 24 24"><path d="M9.5 7l5 5-5 5"/></svg>
              </span>
              <!-- on a narrow screen the middle folders are wound up in the first chevron: this shows them again -->
              <button class="crumb__spool" type="button" aria-expanded="false" hidden data-spool></button>
            </li>
            <li class="crumb" data-id="projects">
              <a class="crumb__link" href="#"><span class="crumb__name"><span class="crumb__text">Projects</span></span></a>
              <span class="crumb__sep" aria-hidden="true" data-sep><svg viewBox="0 0 24 24"><path d="M9.5 7l5 5-5 5"/></svg></span>
            </li>
            <li class="crumb" data-id="harbour">
              <a class="crumb__link" href="#"><span class="crumb__name"><span class="crumb__text">Harbour Museum</span></span></a>
              <span class="crumb__sep" aria-hidden="true" data-sep><svg viewBox="0 0 24 24"><path d="M9.5 7l5 5-5 5"/></svg></span>
            </li>
            <li class="crumb" data-id="exhibition">
              <a class="crumb__link" href="#" aria-current="page"><span class="crumb__name"><span class="crumb__text">Exhibition</span></span></a>
              <span class="crumb__sep" aria-hidden="true" data-sep><svg viewBox="0 0 24 24"><path d="M9.5 7l5 5-5 5"/></svg></span>
            </li>
          </ol>
          <!-- the hook at the end of the tape: it shows the folders inside the current one -->
          <button class="hook" type="button" aria-expanded="false" aria-controls="crumbs-folders" data-hook>
            <span class="hook__body" aria-hidden="true">
              <span class="hook__plate" data-plate></span>
              <svg class="hook__chevron" viewBox="0 0 24 24"><path d="M9.5 7 L14.5 12 L9.5 17"/></svg>
            </span>
          </button>
          <div class="kids" id="crumbs-folders" role="group" hidden data-kids></div>
        </div>
      </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.

24 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 rewinding breadcrumbs” from Animorio and fit it into my site

What it does

On a white background, alone, a light grey bar with the path of a design studio's file drive: the disk icon with Files, then Projects, Harbour Museum and Exhibition, the folder you are in, written in black; between one folder and the next a grey chevron, and at the end of the path a hook, a small yellow square with its own chevron, like the hook of a tape measure. On arrival there is only Files with the hook beside it: the hook pulls and the whole path comes out from under the first chevron like a tape, the letters taut and a little apart, closing up as the hook stops. Pointing at a folder higher up, the folders after it fade back and lean a few pixels towards its chevron, which turns black: that is what you would leave. Choosing it, its chevron opens like a mouth and the tape rewinds into it: the reel pulls from under the chevron, so the nearest letters spread apart and slip under first, cut along the shape of the chevron, the rest follows faster and faster and the hook comes home last, squashing in the clack and covering the chevron. The hook shows the folders inside the one you are in: pressed, it sinks, its chevron bends down and the folders come out from under it as a strip; choosing one, the strip goes back under the hook and the hook pulls the new folder out from under the chevron. A folder with no folders inside has a grey hook, which shakes its head when pressed. The bar's right edge follows the hook. On a phone a long path gathers up: the folders in between wind up inside the first chevron, which shows one more chevron for each folder it holds; tapped, it unwinds them and the strip scrolls sideways.

How it works

Each letter in its place

At rest the words are plain text. When the tape starts, every word on it is copied letter by letter into absolute spans, put exactly where the browser had put its letters: each one's place is read with a Range over one character at a time, so the kerning stays. The text underneath turns invisible but keeps its size, and at the end the copies go.

A string of weights

Each letter, each chevron and the hook are weights on a string worked out in steps of half a millisecond (shorter for a stiffer string, which otherwise blows up), with the frame step capped at 1/30 of a second. The string only pulls, like twine: where it is taut the letters spread. And the letters can never come closer than they sit in the word: when the tape stops they knock together and bounce, sharing the knock like two weights.

The reel and the hook

Rewinding, an unseen point under the chevron pulls the tape with a GSAP tween that starts at once and speeds up; going down, the hook pulls it, with a tween that gets going in a few hundredths and then brakes. The bar the tape runs on rubs on it, so the letters furthest from what pulls lag behind: the ones near the chevron spread when the tape goes in, the ones near the hook when it comes out.

The chevron that cuts

Each folder on the tape has a polygon clip-path with the outline of the chevron it goes into: whatever is left of the outline is under the chevron. A letter goes first in its middle, at the tip, then above and below, as if slipping under a plate. The final path is measured before starting (hiding for an instant what is leaving), so when the tape stops everything is already where the page puts it, to the pixel.

The folders in between in the first chevron

If the path does not fit, the folders in between wind up in the first chevron with the same tape, leaving the last two, and for each one the chevron gains one more chevron, a stack that is also the button to unwind them. The items are links in an ordered list inside a nav with aria-label Breadcrumb, the current one has aria-current; the hook is a button with aria-expanded. The library's preview clicks the bar (a click with no pointer on the nav) and each click makes one move of a little tour up and down the drive.

Values to change

NameFileDefaultWhat it changes
UNROLLscript.js0.55The seconds the hook takes to pull a new folder out (a little more for a long name).
REWINDscript.js0.4The seconds the tape takes to rewind into the chevron of the folder chosen.
STRETCHscript.js1How far the letters spread while the tape runs (0 a stiff steel tape, 2 like toffee).
BOUNCEscript.js0.35How hard the letters bounce off each other when the tape stops (0 not at all).
LEANscript.js6How many pixels the folders after a pointed one lean towards its chevron.
KEEPscript.js2On a narrow screen, how many folders stay at the end of a long path, besides the first.

Try them in the Playground

When to use it

For the breadcrumbs of an app where people go down and back up a lot: a file drive, a project tool, a shop's catalogue with its categories, a manual in chapters. The hook at the end is also a shortcut to go down without going through the page, and the stack of chevrons keeps a long path readable on a phone.

On phones

The bar stays 56 pixels tall and at most as wide as the screen less 16 pixels a side (358 on a 390 phone); the first folder keeps only its icon. If the path does not fit, the folders in between wind up in the first chevron and the last two stay: with four levels there is Files, a stack of two chevrons, Harbour Museum and Exhibition. Tapping the stack unwinds them and the strip scrolls sideways, with fading edges; the folders offered by the hook scroll along with the strip keeping the hook in sight, and going down the path makes room before the hook pulls the new folder out. A finger down on a folder does what the mouse over it does: the folders after fade back and lean. The hook and the stack take a tap over 44 pixels.

With reduced motion

No tape and no moving letters: the folders that leave fade out, the hook fades out and back in at its new place, the new folder fades in; the folders offered fade in and out and the first chevron's stack changes without moving. No leaning, no clack and no press that shrinks.

Pitfalls

  • The contact solver moved each of the two touching letters by half: the letter pushed towards the hook touched another one already settled and the tape stayed squeezed, with the first word sliding back to its place slowly, two pixels in half a second. Now only the letter further from what pulls moves, in a single sweep from the hook (or the reel) to the other end.
  • The first try at that fix gave the whole bounce to the letter moved: each letter set off faster than its neighbour and along the row the speed multiplied, until the words flew out of the bar. The position is fixed on one side only, but the knock is shared by the two weights, and momentum is kept.
  • The chevron after the last folder is hidden with :last-child, but to measure where the hook ends the folders leaving were only hidden: they were still children of the list, the chosen folder's chevron still counted and at the end the hook jumped by 24 pixels. The measure now hides it too.
  • With the stiffness at its lowest (STRETCH 0) the fixed step of one millisecond was too long for the chain's fastest wobble and the tape blew up. The step is now worked out from the stiffness.
  • The hook's chevron, turned 90 degrees to say open, looked like a tick halfway round. Now the path bends from the chevron pointing on to the one pointing down by moving its points, and halfway it is a dash; and the two paths are written in absolute coordinates with spaces, because tweening 5-5 GSAP glued the numbers into 50.26.
  • On a phone the frame grew to the path, because the page grid's column took the content's size: the path never gathered up and spilled over. The column is now minmax(0, 1fr).
  • Pointing at a folder the tape leans towards the chevron; on the click the reel started from a straight tape and the first letter, too close, was pushed back: a little hop to the right before rewinding. Now the reel starts already pulled by as much as the tape leaned.
  • The folders offered came out one after the other, but starting all from the same point under the hook the later ones caught up with the first and covered them. Now they come out together as one strip, and on a phone the sideways scroll goes with it instead of coming after.

Libraries

GSAP 3.15.0, Albert Sans (font variabile) 5.3.0.

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

Testing

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