Skip to content
animorio
IT
Back to the library

The layout grid transition

TransitionsGSAP, CSS onlyMediumCompressed weight: Demo 7.5 KBGSAP 28 KBFreeDownload the zip

A minimal click page change: the page shows its layout grid, the thin columns it is set on, and the columns lift one after another like piano keys, carrying away the pieces of the old page. They fall back with the new page, each with its own bounce, and the title comes together in a ripple.

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 layout grid transition</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <!-- the first page: everything sits on the columns of the layout grid -->
    <section class="page page--a is-on" data-page="a" aria-label="Index">
      <header class="bar">
        <span class="brand">Kolm</span>
        <nav class="nav" aria-label="Pages">
          <a class="w" href="#index" aria-current="page"><span class="w__t">Index</span></a>
          <a class="w" href="#work" data-go="b"><span class="w__t">Work</span></a>
        </nav>
      </header>
      <div class="slab" aria-hidden="true"></div>
      <h1 class="big big--a" data-fit><span class="big__line">Quiet</span><span class="big__line">buildings.</span></h1>
      <p class="lede" data-late>A practice of four architects. We draw slowly, build little and keep every line on the grid.</p>
      <a class="go w" href="#work" data-go="b" data-autoclic data-late>
        <span class="w__t">See the work</span>
        <svg class="go__arrow" viewBox="0 0 26 12" aria-hidden="true"><path class="go__shaft" d="M1 6h22"/><path d="M18.5 1.5 23.5 6l-5 4.5"/></svg>
      </a>
      <footer class="foot">
        <span>Architecture and interiors</span>
        <span>Since 2014</span>
      </footer>
    </section>

    <!-- the second page: dark, like the black keys -->
    <section class="page page--b" data-page="b" aria-label="Work" aria-hidden="true">
      <header class="bar">
        <span class="brand">Kolm</span>
        <nav class="nav" aria-label="Pages">
          <a class="w" href="#index" data-go="a"><span class="w__t">Index</span></a>
          <a class="w" href="#work" aria-current="page"><span class="w__t">Work</span></a>
        </nav>
      </header>
      <h2 class="big big--b" data-fit><span class="big__line">Selected work</span></h2>
      <ul class="list" aria-label="Projects">
        <li class="row"><span class="row__rule" data-rule></span><span class="row__name">House on a slope</span><span class="row__kind">Dwelling</span><span class="row__year">2025</span></li>
        <li class="row"><span class="row__rule" data-rule></span><span class="row__name">Two rooms</span><span class="row__kind">Interior</span><span class="row__year">2023</span></li>
        <li class="row"><span class="row__rule" data-rule></span><span class="row__name">Small library</span><span class="row__kind">Public</span><span class="row__year">2021</span></li>
      </ul>
      <a class="go go--back w" href="#index" data-go="a" data-autoclic data-late>
        <svg class="go__arrow" viewBox="0 0 26 12" aria-hidden="true"><path class="go__shaft" d="M25 6H3"/><path d="M7.5 1.5 2.5 6l5 4.5"/></svg>
        <span class="w__t">Back to index</span>
      </a>
      <footer class="foot">
        <span>Built and in progress</span>
        <span>Since 2014</span>
      </footer>
    </section>

    <!-- the keys (slices of a page, one per column) and the layout grid drawn on top: both built by the script -->
    <div class="keys" data-keys aria-hidden="true"></div>
    <div class="grid" data-grid aria-hidden="true"></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.

40 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 layout grid transition” from Animorio and fit it into my site

What it does

The site of a made-up architecture studio, Kolm, in two pages: the first is light, with a huge headline, Quiet buildings., a red block standing on two columns and a line of text; the second is dark, with Selected work and three projects in a row. Everything sits on an eight-column grid. On load the grid draws itself down from the top, column after column, like the guides in a design tool, and the first page drops into the columns one at a time: each column lands, bounces twice and settles, and its guide lights up for a moment as it touches down. Then the grid draws away into the bottom and the text and the link rise into place. A click on See the work brings the grid back over the page; each column dips a hair, like a key pressed down, then flies off the top with its slice of the page, one after another from left to right. For an instant only the empty grid is left, then the columns fall back with the dark page and the new title comes together in pieces, each piece with its own bounce. The rules of the list draw in from the left and the link back rises last. A click on Back to index runs the same way from the right, like a scale going down.

How it works

One grid

Both pages are CSS grids with the same columns: grid-template-columns: repeat(var(--cols), minmax(0, 1fr)), the same margin and the same gap. The script works out the columns, margin and gap from the width and writes them as variables, together with where each piece sits (for example --at-slab: 6 / span 2), so changing COLUMNS is enough to lay everything out again.

The keys are slices of the page

The real pages are never cut. For every column the script makes a div with overflow hidden, from the middle of the gap on its left to the middle of the gap on its right, and puts in it a copy of the whole page shifted by -x: each key shows only its slice, and together they cover the page with no seams. In the copies data-autoclic and data-go are removed and the links leave the Tab order.

Pressed, then gone

Each key dips DIP pixels in 0.12 seconds with power2.out, then rises off the screen with power3.in, which starts slow and speeds up. The next key goes STAGGER seconds later, in the same order the grid drew itself: each column leaves as soon as its guide is in place.

The fall and the bounce

Each key of the new page starts as soon as its own has left and falls with power2.in, like a weight. Once down it rises BOUNCE pixels with power2.out and drops back with power2.in, then the same again at a quarter of the height and half the time: two real bounces, not an elastic. In the same instant the guide of its column lights up and fades in half a second. Since the keys arrive staggered, so do the bounces, and the title comes together in a ripple.

Direction, phone and reduced motion

Each change is one timeline, with timeScale for SPEED; a click that comes while the page is changing waits in a queue. At the end the real page takes the keys' place, the grid draws away into the bottom and the last details (the rules of the list, the text, the link) arrive last. On a phone the grid has half the columns and the pieces stack one under the other. With reduced motion the grid fades in, the pages swap with a fade and the grid fades away.

Values to change

NameFileDefaultWhat it changes
COLUMNSscript.js8The columns of the grid, and so the keys, on a wide screen; a phone uses half of them.
STAGGERscript.js0.07The seconds between one key and the next: 0 = they all lift and fall together.
LIFTscript.js0.55The seconds a key takes to rise off the screen with the old page.
DROPscript.js0.5The seconds a key takes to fall back with the new page.
BOUNCEscript.js14How many pixels a key bounces when it lands: 0 = it just stops.
DIPscript.js5How many pixels a key dips, as if pressed, before it lifts: 0 = it goes at once.
SPEEDscript.js1The speed of everything: 2 is twice as fast, 0.5 half as fast.

Try them in the Playground

When to use it

To move from one page to another on a site built on a grid you can feel: an architecture or graphic design studio, a portfolio, a magazine, an archive of projects, the step from the home page to the list of work. It looks best with a light page and a dark one, like the white and black keys.

On phones

The same transition with the sizes adapted: the grid has four columns instead of eight, so four keys, the titles shrink to fit the width, the red block sits above the headline and the text goes above the link. A tap on the link starts it and brings it back.

With reduced motion

Nothing moves: the grid fades in, the new page fades in over the old one with everything already in place, then the grid fades away.

Pitfalls

  • The details that arrive last (the text, the link, the rules of the list) were prepared, moved and transparent, in a timeline callback. With a jump forward, like progress(1) when the window is resized halfway through a change, the tween that raises them had already started from the old values and the page was left without its link: now they are prepared while the timeline is built, on the page that is still hidden.
  • The copies inside the keys also carry the inline styles GSAP wrote: the rules of the list, already drawn on the previous visit, had an inline transform and showed up in the falling keys before their time. The rule that hides them in the copies has !important and, once they are drawn, GSAP removes its styles with clearProps.
  • With keys as wide as the columns, at rest the grey background showed in the gaps between them: each key runs from the middle of the gap on its left to the middle of the gap on its right, the first and the last out to the edges.
  • The copies of the page carried data-autoclic with them: the autopilot counts every marked element and clicked the copies. data-autoclic and data-go are removed from the copies.
  • On a phone the red block, tall enough to reach the headline, ended up under the letters: with four columns it sits in its own row, above the headline.

Libraries

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

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

Testing

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