Skip to content
animorio
IT
Back to the library

The exploded sneaker

Scroll, SVGGSAPAdvancedCompressed weight: Demo 19 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

Scroll inside the preview

A running shoe on a drawing bench: as you scroll the laces come out first, then the whole shoe opens into an exploded view, layer by layer (tongue, upper, heel counter, insole, midsole, outsole), and every part gets a leader line with the name of its material. A scanner sweeps across the parts and dips them in a new colour, then the shoe goes back together from the bottom up, one part at a time, with a bounce at every landing.

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 exploded sneaker</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the header of the made-up running shoe maker -->
  <header class="testata">
    <p class="marchio">Ondo<span>Lab</span></p>
    <nav class="menu" aria-label="Main">
      <a href="#banco">Road</a>
      <a href="#banco">Trail</a>
      <a href="#fine">Stores</a>
    </nav>
  </header>

  <main>
    <!-- the bench: a tall section with a still stage; scrolling takes the shoe apart and puts it back together -->
    <section class="banco" id="banco" data-banco>
      <div class="palco" data-palco>
        <!-- the model's name, huge, behind everything: its letters spread with the parts -->
        <p class="sfondo" aria-hidden="true" data-sfondo>
          <span>S</span><span>T</span><span>R</span><span>A</span><span>T</span><span>A</span>
        </p>

        <svg class="mondo" data-mondo aria-hidden="true"></svg>

        <!-- the leader lines and the labels of the materials (the script places them every frame) -->
        <svg class="fili" data-fili aria-hidden="true"></svg>
        <div class="etichette" data-etichette>
          <article class="etichetta" data-parte="laces">
            <h3 class="etichetta__nome"><span>Laces</span></h3>
            <p class="etichetta__materia"><span>Recycled polyester, flat weave</span></p>
            <p class="etichetta__dato"><span>6 g</span></p>
          </article>
          <article class="etichetta" data-parte="tongue">
            <h3 class="etichetta__nome"><span>Tongue</span></h3>
            <p class="etichetta__materia"><span>Gusseted knit, 3 mm padding</span></p>
            <p class="etichetta__dato"><span>14 g</span></p>
          </article>
          <article class="etichetta" data-parte="upper">
            <h3 class="etichetta__nome"><span>Upper</span></h3>
            <p class="etichetta__materia"><span>Engineered mesh, one piece</span></p>
            <p class="etichetta__dato"><span>58 g</span></p>
          </article>
          <article class="etichetta" data-parte="counter">
            <h3 class="etichetta__nome"><span>Heel counter</span></h3>
            <p class="etichetta__materia"><span>Moulded TPU cup</span></p>
            <p class="etichetta__dato"><span>12 g</span></p>
          </article>
          <article class="etichetta" data-parte="insole">
            <h3 class="etichetta__nome"><span>Insole</span></h3>
            <p class="etichetta__materia"><span>Perforated foam, 4 mm</span></p>
            <p class="etichetta__dato"><span>16 g</span></p>
          </article>
          <article class="etichetta" data-parte="midsole">
            <h3 class="etichetta__nome"><span>Midsole</span></h3>
            <p class="etichetta__materia"><span>Strata foam, 36 mm at the heel</span></p>
            <p class="etichetta__dato"><span>98 g</span></p>
          </article>
          <article class="etichetta" data-parte="outsole">
            <h3 class="etichetta__nome"><span>Outsole</span></h3>
            <p class="etichetta__materia"><span>Rubber lugs where you land</span></p>
            <p class="etichetta__dato"><span>44 g</span></p>
          </article>
        </div>

        <!-- the opening, next to the whole shoe -->
        <div class="apertura" data-apertura>
          <p class="apertura__etichetta" data-entra>The Strata, on the bench</p>
          <h1 class="apertura__titolo">
            <span class="riga"><span data-riga>Seven parts.</span></span>
            <span class="riga"><span data-riga><em>One stride.</em></span></span>
          </h1>
          <p class="apertura__testo" data-entra>Our everyday runner, taken apart layer by layer. Scroll to pull every piece out, then watch it go back together in a new colour.</p>
          <p class="cenno" data-entra>
            Scroll to take it apart
            <svg viewBox="0 0 24 32" aria-hidden="true"><path d="M12 3V27M4 19L12 28L20 19" /></svg>
          </p>
        </div>

        <!-- a caption for every moment of the bench -->
        <div class="didascalie" data-didascalie>
          <p class="didascalia"><span>Laces out first.</span></p>
          <p class="didascalia"><span>Then the stack comes apart.</span></p>
          <p class="didascalia"><span>Seven parts, 248 g.</span></p>
          <p class="didascalia"><span>Dipped in <em data-nome-colore>Glacier</em>.</span></p>
          <p class="didascalia"><span>Back together, bottom up.</span></p>
        </div>

        <!-- the close, where the opening was -->
        <div class="chiusura" data-chiusura>
          <p class="chiusura__etichetta" data-chiude>Strata in <span data-nome-colore>Glacier</span></p>
          <h2 class="chiusura__titolo">
            <span class="riga"><span data-chiude-riga>Same shoe.</span></span>
            <span class="riga"><span data-chiude-riga><em>New weather.</em></span></span>
          </h2>
          <p class="chiusura__prezzo" data-chiude>$140, ships in March</p>
          <a class="pillola" href="#fine" data-chiude><span class="pillola__fondo"></span><span class="pillola__testo">Pre-order</span></a>
        </div>

        <!-- the colourways: a tap dips the shoe again -->
        <div class="colori" data-colori role="group" aria-label="Colourway">
          <button type="button" class="colore" data-colore="clay"><span>Clay</span></button>
          <button type="button" class="colore" data-colore="glacier"><span>Glacier</span></button>
          <button type="button" class="colore" data-colore="ember"><span>Ember</span></button>
        </div>
      </div>
    </section>

    <footer class="fine" id="fine">
      <p class="fine__frase">Built in layers. <em>Worn as one.</em></p>
      <p class="fine__nota">Ondo Lab, running shoes made to be taken apart and resoled.</p>
    </footer>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.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.

87 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 exploded sneaker” from Animorio and fit it into my site

What it does

The page of a made-up running shoe brand, Ondo Lab. At the top, on a light grey background with the grid of a technical drawing, there is the title «Seven parts. One stride.» and next to it the whole shoe, the Strata, in the Clay colourway (oat upper, terracotta overlays, a green wave on the side), which drops onto the bench with a bounce when the page opens. Behind it, huge and only outlined, the model’s name. As you scroll the stage holds still. The laces come out first: the zigzag between the eyelets loosens into a soft string and rises up. Then the shoe opens: the tongue rises and tilts, the upper lifts, the heel counter moves back, the insole is left uncovered over the midsole, the midsole and the outsole go down, each with a small overshoot and settle. The camera pulls back just enough to keep every part on the screen, the grid gets clearer and the letters of the name spread out with the parts. Next to every part a leader line draws itself and the label rises line by line: name, material, weight. The parts float gently, each to its own rhythm. Then comes the scanner, a thin line with two arrowheads and the name of the new colour: moving from left to right it dips every part in the Glacier colourway (ice, deep blue, a dark outsole, a coral wave), and every part gives a little jolt when the line passes its middle. The labels leave and the shoe goes back together from the bottom up: outsole, midsole, insole, upper, heel counter, tongue and the laces last, back in their zigzag; every part lands with a spring. In the end the shoe moves back to the side and the close comes in, «Same shoe. New weather.», with the price and the button. At the bottom a caption for every moment; at the bottom right three colour buttons (Clay, Glacier, Ember): a tap dips the colour on show at that moment, and every part does a little hop from the bottom up. With the mouse over a loose part the part rises a little and the name on its label lights up; over the whole shoe, the shoe does a little hop.

How it works

A bench and a camera

The section is SCROLL_LENGTH screens tall and holds a sticky stage 100lvh tall with a single SVG whose viewBox is as big as the stage in pixels. The shoe is drawn side on in world units (about a thousand long) inside a group that works as a camera: every frame the box of the parts, as far as they are out, is worked out and fitted into a free area of the stage, next to the title at the start and at the end, in the middle with room for the labels in between.

One profile, seven parts

The bottom of the outsole, the thickness of the foam and the line on top of the midsole are three small functions of x; outsole, midsole, insole and the lower edge of the upper are drawn along them, so the parts always fit. The insole is the footbed seen from just above: its half width at every x, squashed, over the midsole’s line. Every part has a pivot, an exit vector (one for wide screens and one for narrow ones), a box and a point where its leader line starts.

Time as the only number

A paused timeline, driven by the scroll with scrub, moves a few numbers: how far each part is out (with back.out on the way out and a spring on the way back), where the camera is, where the scanner passes, how much of every leader line is drawn. The label lines, the captions and the close are tweens in the same timeline. A ticker turns the numbers into SVG transforms, lines and positions, and adds the gentle drift of the hanging parts.

Laces and labels

The laces are a path redrawn every frame: the points go from the zigzag between the eyelets to a soft wave, and the curve handles grow by the same amount, so the string goes from angular to soft. The labels are HTML over the stage: the part’s attachment point is taken to the screen with the same rotation as the part and the camera, the labels on each side push each other apart from top to bottom, and the leader line draws itself with stroke-dashoffset.

Two skins and a scanner

Every part is drawn twice: underneath in the starting colours, on top in the new ones, and the colours are --t- variables taken from two sets of variables on the SVG. The new skin has a clipPath with a rectangle that reaches as far as the scanner’s line, taken into the part’s own space. The colour buttons tween the colours of the skin on show and rewrite the variables at every step, with a hop from every part.

Values to change

NameFileDefaultWhat it changes
SCROLL_LENGTHscript.js8How many screens of scrolling the whole bench lasts.
SPREADscript.js1How far the parts fly apart in the exploded view.
TILTscript.js1How much each part tilts while it is out (0 keeps them level).
FLOATscript.js1How much the hanging parts drift (0 holds them still).
BOUNCEscript.js1How much the parts bounce when they land back (0 is a plain stop).
EYELETSscript.js6How many eyelets the laces go through.
LABELSscript.jstrueShow the leader lines and the labels of the materials.
--glacier-tomaiastyle.css#d3e3ecThe upper of the new colourway; next to it are Glacier’s other five colours and those of Clay (the starting colourway) and Ember.

Try them in the Playground

When to use it

To show what a product is made of: a shoe, a backpack, a technical jacket, flat-pack furniture, a device. It works well on a product page, for the launch of a new colourway or of a repairable product, and anywhere you want to tell materials and weights without a table.

On phones

The same animations with the sizes adapted: the title sits at the top and the shoe below it. In the exploded view the parts line up in rows, one under the other (the heel counter next to the tongue), and every label sits in the space above its part, with the name and the material; the leader line goes straight up. The captions and the colour buttons sit at the bottom. A tap on a part lifts it; on the whole shoe, it makes it hop.

With reduced motion

No flying parts, no drift, no bounces and no smooth scrolling: the stage shows four still pictures (the whole shoe in the starting colour, the exploded view with its labels, the exploded view dipped in the new colour, the shoe back together with the close) and scrolling fades in the next. The colour buttons change the colour with a fade.

Pitfalls

  • The mesh texture is an SVG pattern, and its dots do not inherit CSS variables from the element that uses it but from the pattern’s own ancestors: with the upper’s colour they would be left with no colour. The dots are see-through black and white, so they darken and lighten any colourway.
  • The new skin’s clipPath, with userSpaceOnUse, is in the coordinates of the element using it, that is the part already moved: the scanner’s line has to be taken into the part’s space by removing its offset, or the moved parts would be dipped too early or too late.
  • The camera frames the box of the parts with the exit capped at 1: with the spring on the way back the parts go a little past, and a box changing with them would make the whole framing shake.
  • On the phone the labels on both sides covered the parts: in portrait the exploded view has its own exit vector for every part, in rows, with room for a label above each row.
  • Moving the mouse over the whole shoe crosses several parts one after the other, and the shoe would hop for every part: one hop at a time, at most one a second. On the phone a tap uses click and not pointerdown, or every drag to scroll over the shoe would make it hop.

Libraries

GSAP 3.15.0, Lenis 1.3.26, Archivo (font variabile) 5.3.0, JetBrains Mono (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 19 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.

Testing

Tested on 13 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 animations