
The send button
Buttons, Transitions, SVG
NewFree
The delivery address in a shop’s checkout: name, street, town, a postcode checked against the shape of the chosen country, and country. With everything right the card itself becomes the shipping label: the edges of the fields fade, the card closes and takes the black rules of a label, the words fly from the fields to their lines changing size and weight, the route is typed into the black box and a print head crosses the label printing a real Code 128 barcode.
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 address that becomes a label</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist-mono@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the delivery address of a checkout: with every field right, the card turns into the shipping label, the words
fly from the fields to their lines and a real Code 128 barcode is printed under them. Sending is pretended:
see post() in the script -->
<div class="ship" data-ship data-autoclic>
<div class="sheet" data-sheet>
<form class="addr" action="#" novalidate aria-labelledby="ship-title" data-form>
<h2 class="addr__title" id="ship-title">Delivery address</h2>
<div class="field" data-field="name">
<label class="field__label" for="ship-name">Full name</label>
<div class="field__box" data-box>
<input class="field__input" id="ship-name" name="name" type="text" autocomplete="shipping name" autocapitalize="words" spellcheck="false" enterkeyhint="next" maxlength="40" aria-describedby="ship-name-err" aria-invalid="false" data-input>
<span class="field__caret" aria-hidden="true" data-caret></span>
</div>
<p class="field__err" id="ship-name-err" data-err></p>
</div>
<div class="field" data-field="street">
<label class="field__label" for="ship-street">Street and number</label>
<div class="field__box" data-box>
<input class="field__input" id="ship-street" name="street" type="text" autocomplete="shipping address-line1" spellcheck="false" enterkeyhint="next" maxlength="48" aria-describedby="ship-street-err" aria-invalid="false" data-input>
<span class="field__caret" aria-hidden="true" data-caret></span>
</div>
<p class="field__err" id="ship-street-err" data-err></p>
</div>
<div class="addr__row">
<div class="field" data-field="city">
<label class="field__label" for="ship-city">Town or city</label>
<div class="field__box" data-box>
<input class="field__input" id="ship-city" name="city" type="text" autocomplete="shipping address-level2" spellcheck="false" enterkeyhint="next" maxlength="32" aria-describedby="ship-city-err" aria-invalid="false" data-input>
<span class="field__caret" aria-hidden="true" data-caret></span>
</div>
<p class="field__err" id="ship-city-err" data-err></p>
</div>
<div class="field field--post" data-field="post">
<label class="field__label" for="ship-post">Postcode</label>
<div class="field__box" data-box>
<input class="field__input" id="ship-post" name="post" type="text" autocomplete="shipping postal-code" autocapitalize="characters" autocorrect="off" spellcheck="false" enterkeyhint="next" maxlength="10" aria-describedby="ship-post-err" aria-invalid="false" data-input>
<span class="field__caret" aria-hidden="true" data-caret></span>
</div>
<p class="field__err" id="ship-post-err" data-err></p>
</div>
</div>
<div class="field field--country" data-field="country">
<label class="field__label" for="ship-country">Country</label>
<div class="field__box" data-box>
<select class="field__input field__select" id="ship-country" name="country" autocomplete="shipping country" data-country>
<option value="GB">United Kingdom</option>
<option value="IE">Ireland</option>
<option value="IT">Italy</option>
<option value="DE">Germany</option>
<option value="FR">France</option>
<option value="US">United States</option>
</select>
<svg class="field__chev" viewBox="0 0 12 12" aria-hidden="true"><path d="M2.5 4.5 6 8l3.5-3.5"/></svg>
</div>
</div>
<div class="addr__foot">
<button class="send" type="submit" data-send>
<span class="send__bg" aria-hidden="true"></span>
<span class="send__label">Ship here</span>
</button>
</div>
</form>
<!-- the label the card turns into: drawn for the eye, the form above stays the real thing -->
<div class="label" aria-hidden="true" data-label>
<div class="label__from">
<span class="label__cap">From</span>
<span>Larkspur Goods · Unit 4, Mill Lane · Bristol</span>
</div>
<div class="label__main">
<div class="label__to">
<span class="label__cap">Ship to</span>
<span class="label__line label__line--name" data-to="name"></span>
<span class="label__line" data-to="street"></span>
<span class="label__line label__line--city"><span data-to="city"></span> <span data-to="post"></span></span>
<span class="label__line label__line--country" data-to="country"></span>
</div>
<div class="label__sort" data-sort>
<span class="label__cap label__cap--inv">Route</span>
<span class="label__route" data-route></span>
</div>
</div>
<div class="label__code">
<svg class="label__bars" data-bars preserveAspectRatio="none"></svg>
<span class="label__head" data-head></span>
<span class="label__track" data-track></span>
</div>
</div>
</div>
<div class="ship__after" data-after>
<p class="after__line"><span data-after-text>Arrives Thursday, tracked all the way.</span> <button class="after__change" type="button" data-change>Change</button></p>
</div>
<p class="sr" role="status" 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>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.
33 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 address that becomes a label” from Animorio and fit it into my siteEvery field has its label, shipping autocomplete, aria-invalid and aria-describedby to the line under it. The postcode is checked against the shape of the chosen country (United Kingdom, Ireland, Italy, Germany, France, United States), turns to capitals as you type without moving the caret and takes the right space when you leave it. The error line has a height of its own that opens and closes on a tween, so the fields below move down and up softly.
On sending, a copy of each field’s words is laid on it in the same type and place, and the real words turn transparent. The label’s lines, already filled but invisible, give the destination: x, the middle of the line, the size and the weight. Every copy flies with x, y, scale and fontWeight on one timeline, staggered by STAGGER; halfway the lines in capitals take their capitals, and on arrival the copy gives way to the real line.
At the same time the names and edges of the fields fade, the height of the card goes from the form’s to the label’s, the corners from 20 to 6 pixels, the edge from grey to black with a shadow: the card is not replaced, it changes job. Going back plays the flight in reverse, starting from the lowest line, so the words going down never cross the ones waiting above.
The tracking number comes from the address (an FNV hash of the lines, nine digits, between the sender’s two letters and the country). The barcode is Code 128 set B: the start, every character with its six widths of bar and space, the check character (weighted sum modulo 103) and the stop, with ten quiet modules either side. The bars are SVG rectangles on a viewBox in modules, a whole number of pixels wide (MODULE) and with shape-rendering crispEdges, so they scan.
Printing is an object going from 0 to 1 on GSAP in PRINT seconds, with no ease: at every step the barcode’s clip-path opens from the left up to that point and the print head’s orange line sits there, while the number is typed character by character at the head’s pace. The start and end of the postcode are typed into the Route box.
| Name | File | Default | What it changes |
|---|---|---|---|
FLIGHT | script.js | 0.8 | The seconds the words take to fly from the fields to the label. |
STAGGER | script.js | 0.07 | The seconds between one word taking off and the next. |
PRINT | script.js | 0.9 | The seconds the print head takes to cross the barcode. |
MODULE | script.js | 2 | The width of the thinnest bar, in pixels (it drops if the label is narrow). |
SENDER | script.js | LG | The two letters the tracking number starts with. |
WAIT | script.js | 0.5 | How many seconds the pretended saving of the address takes. |
In the delivery step of a checkout, in a shop that ships: the label tells the buyer, better than a summary, that the address is right and where the parcel will go. It also suits the address page of an account or a shipping app.
The card takes the width of the screen (358 pixels on a 390 phone), town and postcode stay side by side, the fields are 46 pixels tall and the type 16, so Safari does not zoom. The postcode opens the keyboard in capitals, Country opens the phone’s picker. On the label the route box narrows and the barcode keeps whole modules, centred.
No flights, no jolts and no print head: the error lines fade in, and on sending the form fades away and the label appears already printed, with the whole barcode and number. Change does the same in reverse.
GSAP 3.15.0, Geist (font variabile) 5.3.0, Geist Mono (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 12 KB; the libraries: GSAP 28 KB.
Tested on 19 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.