
Column shutter
Transitions
NewFree
A page change in the minimal style: on a click the page steps back until the whole site shows in a row like a magazine's flatplan, with hairline frames and the page names on a rule. Two pairs of red crop marks run to the chosen page, stretching and springing shut around it, the row brings it to the middle and the view walks back in.
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 flatplan 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 whole site laid out in a row, like the pages of a magazine pinned up on the wall: the camera moves over it -->
<div class="track" data-track>
<section class="page page--index" data-page aria-label="Index">
<header class="bar">
<a class="brand" href="#index" data-go="0">Marlow</a>
<nav class="nav" aria-label="Pages">
<a href="#index" data-go="0" aria-current="page">Index</a>
<a href="#work" data-go="1">Work</a>
<a href="#studio" data-go="2">Studio</a>
<a href="#contact" data-go="3">Contact</a>
</nav>
</header>
<div class="body">
<p class="kicker">Furniture, rooms and type</p>
<h1 class="title" data-title>Quiet work.</h1>
<p class="lede">A small studio that makes a few good things each year, and keeps them going for a long time.</p>
</div>
<footer class="foot">
<span class="note">Since 2014</span>
<a class="next" href="#work" data-go="1" data-autoclic>
<span class="next__text">Next, Work</span>
<span class="next__arrow" aria-hidden="true"><span class="next__shaft"></span><svg class="next__head" viewBox="0 0 8 12"><path d="M1.5 1.5 6.5 6l-5 4.5"/></svg></span>
</a>
</footer>
</section>
<section class="page page--work" data-page aria-label="Work">
<header class="bar">
<a class="brand" href="#index" data-go="0">Marlow</a>
<nav class="nav" aria-label="Pages">
<a href="#index" data-go="0">Index</a>
<a href="#work" data-go="1" aria-current="page">Work</a>
<a href="#studio" data-go="2">Studio</a>
<a href="#contact" data-go="3">Contact</a>
</nav>
</header>
<div class="body">
<h2 class="title" data-title>Work</h2>
<ul class="list">
<li><span>Harbour chair</span><span class="list__kind">Oak, wool</span><span>2025</span></li>
<li><span>Linden lamp</span><span class="list__kind">Brass, paper</span><span>2024</span></li>
<li><span>Atlas shelf</span><span class="list__kind">Ash</span><span>2023</span></li>
</ul>
</div>
<footer class="foot">
<span class="note">Three of forty</span>
<a class="next" href="#studio" data-go="2" data-autoclic>
<span class="next__text">Next, Studio</span>
<span class="next__arrow" aria-hidden="true"><span class="next__shaft"></span><svg class="next__head" viewBox="0 0 8 12"><path d="M1.5 1.5 6.5 6l-5 4.5"/></svg></span>
</a>
</footer>
</section>
<section class="page page--studio" data-page aria-label="Studio">
<header class="bar">
<a class="brand" href="#index" data-go="0">Marlow</a>
<nav class="nav" aria-label="Pages">
<a href="#index" data-go="0">Index</a>
<a href="#work" data-go="1">Work</a>
<a href="#studio" data-go="2" aria-current="page">Studio</a>
<a href="#contact" data-go="3">Contact</a>
</nav>
</header>
<div class="body">
<h2 class="title" data-title>Studio</h2>
<div class="cols">
<p>Four people around one long table, a workshop downstairs and a window onto the canal.</p>
<p>We draw everything by hand first, then build it full size, then sit on it for a week.</p>
</div>
</div>
<footer class="foot">
<span class="note">Visits by appointment</span>
<a class="next" href="#contact" data-go="3" data-autoclic>
<span class="next__text">Next, Contact</span>
<span class="next__arrow" aria-hidden="true"><span class="next__shaft"></span><svg class="next__head" viewBox="0 0 8 12"><path d="M1.5 1.5 6.5 6l-5 4.5"/></svg></span>
</a>
</footer>
</section>
<section class="page page--contact" data-page aria-label="Contact">
<header class="bar">
<a class="brand" href="#index" data-go="0">Marlow</a>
<nav class="nav" aria-label="Pages">
<a href="#index" data-go="0">Index</a>
<a href="#work" data-go="1">Work</a>
<a href="#studio" data-go="2">Studio</a>
<a href="#contact" data-go="3" aria-current="page">Contact</a>
</nav>
</header>
<div class="body">
<h2 class="title" data-title>Say hello.</h2>
<p class="lede">Monday to Friday, nine to six. Studio 4, Canal Yard.</p>
</div>
<footer class="foot">
<span class="note">Write any time</span>
<a class="next" href="#index" data-go="0" data-autoclic>
<span class="next__text">Back to the start</span>
<span class="next__arrow" aria-hidden="true"><span class="next__shaft"></span><svg class="next__head" viewBox="0 0 8 12"><path d="M1.5 1.5 6.5 6l-5 4.5"/></svg></span>
</a>
</footer>
</section>
</div>
<!-- the flatplan: hairline frames, the rule with the page names, the crop marks (all placed by the script) -->
<div class="plan" data-plan aria-hidden="true">
<div class="rule" data-rule><span class="rule__line"></span></div>
<div class="crop" data-crop>
<span class="crop__c crop__c--tl"><i></i></span>
<span class="crop__c crop__c--tr"><i></i></span>
<span class="crop__c crop__c--bl"><i></i></span>
<span class="crop__c crop__c--br"><i></i></span>
</div>
</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>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.
62 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The flatplan transition” from Animorio and fit it into my siteThe four pages are real, exactly as big as the screen, and sit side by side inside a single container, GAP times their width apart. The script never moves the pages: it moves the view. The view is two numbers, cx (the page in the middle, which can be 1.4, between two pages) and s (the zoom), and those two numbers make one transform on the container: a translate that puts cx in the middle and scale(s) with the origin at the top left. Stepping back, sliding and walking in are three tweens on two numbers.
The frames, the rule, the ticks, the names and the crop marks are not inside the pages: a one-pixel border shrunk to a third would turn into a third of a pixel and vanish. They live on a layer above, at true size, and on every frame the box(p) function says where page p falls with the view of that moment. The layer shows as much as the view is far: opacity from 0 at full size to 1 at SCALE.
The four crop marks follow two numbers, pl and pr: the page framed by the left pair and the page framed by the right pair. Going forward pr leaves first, with power3.inOut, and STRETCH seconds later pl follows, with back.out: for a moment the two pairs frame different pages and the frame stretches over the ones in between, then the back pair arrives, overshoots by a hair and closes. Going back the roles swap. Each arm draws itself from its corner with scale and back.out.
For a page next door SCALE is enough; for a far one the view steps back until both pages and the ones in between fit in 90 percent of the width, and looks halfway between the two. Then the row slides to the new page while the view is already walking in: the two tweens overlap and the move becomes a single curve. The walk in goes to 1.006 with power3.inOut and settles at 1 with power2.out; meanwhile the letters of the new headline dip 0.045em, one after the other, and spring back with elastic.out.
Each change is one timeline, with timeScale for SPEED. A click that comes while the page is changing waits in a queue and goes as soon as the page fills the screen, without waiting for the last settle. Only the page on screen can be reached with Tab and with screen readers. On a phone the pages are tall and narrow and the flatplan is the same, smaller. With reduced motion nothing moves: the page fades out and the new one fades in already in place.
| Name | File | Default | What it changes |
|---|---|---|---|
SCALE | script.js | 0.3 | How small the pages get in the flatplan: 0.3 is a third of the screen, 0.5 half. For far pages the view steps back further anyway. |
GAP | script.js | 0.12 | The space between two pages, as a share of a page's width. |
OUT | script.js | 0.7 | The seconds of the step back. |
MOVE | script.js | 0.6 | The seconds the crop marks take to run to the next page (a little more for far ones). |
STRETCH | script.js | 0.14 | How far the back pair of crop marks lags behind the front one, in seconds: 0 = the frame moves rigid. |
IN | script.js | 0.8 | The seconds of the walk back into the new page. |
SPEED | script.js | 1 | The speed of everything: 2 is twice as fast, 0.5 half as fast. |
To move from one page to another on a site of a few pages where the whole matters: a designer's or a photographer's portfolio, an architect's studio, a magazine or a small publisher, the presentation of a collection. It shows at a glance where you are and where you're going, so it works best when the pages are few (three to six) and look different from each other.
The same transition with the sizes adapted: the pages are tall and narrow like the screen, the flatplan shows them smaller in a row, with the rule and the names below. The headlines fit the width and a tap on the link takes the trip.
Nothing moves and nothing zooms: the flatplan doesn't show, the page fades out and the new one fades in already in place.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.3 KB; the libraries: GSAP 28 KB.
Tested on 14 October 2026
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.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.