Skip to content
animorio
IT
All components

The form that goes in the kiln

Forms, Transitions, SVG, TextGSAP, CSS onlyAdvancedCompressed weight: Demo 17 KBGSAP 28 KBFreeDownload the zip

The booking form of a pottery’s wheel class, made of clay: a field that is right gets a coat of raw glaze brushed over it, one that is wrong turns iron red and wobbles like a pot off centre. Sent, it goes in the kiln: in a little over two seconds it glows by itself dull red, cherry, orange and yellow, in the true colours of a body that hot computed with Planck’s law, shrinks by twelve per cent like clay and comes out a glazed tile in the glaze chosen, with the booking pressed into it.

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 form that goes in the kiln</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/soft.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the booking form of a pottery's wheel class, made of clay: a field that is right gets a coat of raw glaze
         brushed over it, one that is wrong turns iron red; sent, the slab goes in the kiln, glows from dull red to
         yellow white, shrinks like clay and comes out a glazed tile in the glaze chosen. The booking is pretended:
         see book() in the script -->
    <form class="kiln" action="#" novalidate aria-labelledby="kiln-title" data-kiln data-autoclic>
      <div class="slab" data-slab>
        <div class="face" data-face>
          <div class="head">
            <h2 class="head__title" id="kiln-title">Thursday wheel class</h2>
            <p class="head__sub">Six evenings on the wheel, 7 to 9 pm. Clay, tools and two firings included.</p>
          </div>

          <div class="field" data-field="name">
            <label class="field__label" for="kiln-name">Your name</label>
            <div class="well" data-well>
              <svg class="coat" aria-hidden="true" data-coat></svg>
              <input class="well__input" id="kiln-name" name="name" type="text" autocomplete="name" autocapitalize="words" spellcheck="false" enterkeyhint="next" aria-describedby="kiln-name-msg" aria-invalid="false" data-input>
              <span class="well__caret" aria-hidden="true" data-caret></span>
              <svg class="tick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg>
            </div>
            <div class="field__msg" id="kiln-name-msg" data-msg></div>
          </div>

          <div class="field" data-field="email">
            <label class="field__label" for="kiln-email">Email</label>
            <div class="well" data-well>
              <svg class="coat" aria-hidden="true" data-coat></svg>
              <input class="well__input" id="kiln-email" name="email" type="text" inputmode="email" autocomplete="email" autocapitalize="off" autocorrect="off" spellcheck="false" enterkeyhint="send" placeholder="you@example.com" aria-describedby="kiln-email-msg" aria-invalid="false" data-input>
              <span class="well__caret" aria-hidden="true" data-caret></span>
              <svg class="tick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg>
            </div>
            <div class="field__msg" id="kiln-email-msg" data-msg></div>
          </div>

          <fieldset class="field field--picks" role="radiogroup" aria-labelledby="kiln-date-legend" aria-describedby="kiln-date-msg" aria-required="true" aria-invalid="false" data-field="date">
            <legend class="field__label" id="kiln-date-legend">First Thursday</legend>
            <div class="picks">
              <label class="pick">
                <input type="radio" name="date" value="Thursday 15 October" data-input>
                <span class="pick__body"><svg class="coat" aria-hidden="true" data-coat></svg><span class="pick__main">15 Oct</span><span class="pick__sub">4 seats left</span><svg class="tick tick--pick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg></span>
              </label>
              <label class="pick">
                <input type="radio" name="date" value="Thursday 5 November" disabled data-input>
                <span class="pick__body"><span class="pick__main">5 Nov</span><span class="pick__sub">Full</span></span>
              </label>
              <label class="pick">
                <input type="radio" name="date" value="Thursday 26 November" data-input>
                <span class="pick__body"><svg class="coat" aria-hidden="true" data-coat></svg><span class="pick__main">26 Nov</span><span class="pick__sub">9 seats left</span><svg class="tick tick--pick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg></span>
              </label>
            </div>
            <div class="field__msg" id="kiln-date-msg" data-msg></div>
          </fieldset>

          <fieldset class="field field--picks" role="radiogroup" aria-labelledby="kiln-glaze-legend" aria-describedby="kiln-glaze-msg" aria-required="true" aria-invalid="false" data-field="glaze">
            <legend class="field__label" id="kiln-glaze-legend">Glaze for your first bowl</legend>
            <div class="picks">
              <label class="pick">
                <input type="radio" name="glaze" value="celadon" data-input>
                <span class="pick__body"><svg class="coat" aria-hidden="true" data-coat></svg><svg class="bowl" viewBox="0 0 40 20" aria-hidden="true"><path class="bowl__glaze bowl--celadon" d="M2 3.5h36c0 8.6-7.4 14-18 14S2 12.1 2 3.5z"/><path class="bowl__shine" d="M7.5 7.2c2.2 3.6 6 5.4 10.4 5.8"/></svg><span class="pick__main">Celadon</span><svg class="tick tick--pick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg></span>
              </label>
              <label class="pick">
                <input type="radio" name="glaze" value="tenmoku" data-input>
                <span class="pick__body"><svg class="coat" aria-hidden="true" data-coat></svg><svg class="bowl" viewBox="0 0 40 20" aria-hidden="true"><path class="bowl__glaze bowl--tenmoku" d="M2 3.5h36c0 8.6-7.4 14-18 14S2 12.1 2 3.5z"/><path class="bowl__shine" d="M7.5 7.2c2.2 3.6 6 5.4 10.4 5.8"/></svg><span class="pick__main">Tenmoku</span><svg class="tick tick--pick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg></span>
              </label>
              <label class="pick">
                <input type="radio" name="glaze" value="shino" data-input>
                <span class="pick__body"><svg class="coat" aria-hidden="true" data-coat></svg><svg class="bowl" viewBox="0 0 40 20" aria-hidden="true"><path class="bowl__glaze bowl--shino" d="M2 3.5h36c0 8.6-7.4 14-18 14S2 12.1 2 3.5z"/><path class="bowl__shine" d="M7.5 7.2c2.2 3.6 6 5.4 10.4 5.8"/></svg><span class="pick__main">Shino</span><svg class="tick tick--pick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg></span>
              </label>
            </div>
            <div class="field__msg" id="kiln-glaze-msg" data-msg></div>
          </fieldset>

          <button class="fire" type="submit" data-fire>
            <span class="fire__bg" aria-hidden="true"></span>
            <span class="fire__label" data-fire-label>Book my seat · €240</span>
            <span class="fire__heat" aria-hidden="true" data-heat></span>
          </button>
        </div>

        <!-- what comes out of the kiln -->
        <section class="tile" aria-labelledby="kiln-tile-title" hidden data-tile>
          <span class="tile__shine" aria-hidden="true" data-shine></span>
          <div class="tile__top">
            <p class="tile__kicker"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4.8 10.6l3.4 3.4 7-7.6"/></svg>Seat booked</p>
            <h2 class="tile__title" id="kiln-tile-title" tabindex="-1" data-tile-title>See you at the wheel.</h2>
          </div>
          <dl class="tile__facts">
            <div><dt>First class</dt><dd data-out="date"></dd></div>
            <div><dt>Your bowl’s glaze</dt><dd data-out="glaze"></dd></div>
            <div><dt>Details sent to</dt><dd data-out="email"></dd></div>
          </dl>
          <p class="tile__note">Bring an apron and short nails. Your bowl comes out of its last firing three weeks later.</p>
          <button class="again" type="button" data-again><span class="again__bg" aria-hidden="true"></span><span class="again__label">Book another seat</span></button>
        </section>

        <span class="slab__dark" aria-hidden="true" data-dark></span>
        <span class="slab__glow" aria-hidden="true" data-glow></span>
        <span class="slab__veil" aria-hidden="true" data-veil></span>
        <span class="slab__flame" aria-hidden="true" data-flame></span>
      </div>
      <p class="sr" role="status" aria-live="polite" data-live></p>
    </form>
  </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.

49 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 form that goes in the kiln” from Animorio and fit it into my site

What it does

On a black background a slab of buff stoneware with rounded corners: the title Thursday wheel class, the line Six evenings on the wheel, 7 to 9 pm, two wells pressed into the clay for the name and the email, three tiles for the first Thursday (15 Oct with 4 seats left, 5 Nov struck through and Full, 26 Nov with 9 seats left), three tiles with a little painted bowl for the glaze of the first bowl (Celadon, Tenmoku, Shino) and the cobalt blue button Book my seat · €240. Tapped, a well lightens with a cobalt edge. Typing, a moment after the last key the field reads itself over: if it is right a brush passes over it, the bristles reaching the end one after the other and leaving a chalky coat of raw glaze with its streaks, and a cobalt tick draws itself at the end. If it is wrong when left, the well turns iron red, wobbles like a pot off centre on the wheel and a line with a triangle drops under it saying what is missing (Add the ending, like .com); as soon as the field is right again the error goes and the glaze comes. Choosing a tile, it presses into the slab, takes the cobalt edge, the glaze and the tick, and its neighbour lets go of its own. Pressing Book my seat with something missing, every wrong field wobbles with its message and the focus goes to the first. If all is right the button’s words become Firing with the degrees climbing, the light round the slab goes out as in a closed kiln and the clay begins to glow by itself: dull red near 600 degrees, cherry, orange and at the top, at 1,240 degrees, a light yellow with brighter patches that breathe, while a halo spreads round it; the edges, thinner, light up before the middle. Climbing, the slab shrinks as a whole by twelve per cent; at the top, for a tenth of a second, the form disappears in the light and, cooling from yellow to orange, red and dark, the edge first, it becomes a glossy tile in the glaze chosen (celadon green, tenmoku brown or shino peach) with a highlight that runs across it once (a little over two seconds from the click to a tile that can be read): Seat booked, See you at the wheel, Mara., the first Thursday, the glaze, the email, what to bring and the button Book another seat, which brings back a new form.

How it works

A real form under the clay

Two real inputs with their labels (autocomplete name and email, inputmode email, text at 16 pixels so Safari on phones does not zoom) and two groups of real radios in a fieldset with role radiogroup: the tiles are the radios themselves, invisible over their drawing, so arrows, space, taps and screen readers work by themselves and the Full tile is really disabled. Every field has aria-invalid and aria-describedby pointing at its line underneath; on sending the focus goes to the first wrong field and an aria-live region says what to check, then reads the booking out.

Checking while typing

Every field has three states: at rest, right, wrong. Typing, SETTLE seconds after the last key (a GSAP delayedCall restarted at every key) a field that has become right takes the glaze; one that is not right yet is left alone until it is left, and only then turns red. A red field is read at every key: it is right again as soon as it is, while the words of its error only change after a pause, so they do not flicker between one key and the next. The line underneath comes in with its height animated to auto.

The glaze, brushed on

The glaze is an SVG as big as the well, rebuilt when its size changes: a strip every five or six pixels, with round ends like bristles. On every frame each strip reaches p·(width + 40) less its own delay, taken from two sines out of phase: the edge of the wet glaze is ragged while it runs and straight once it has arrived. Each strip has an opacity of its own, which leaves the streaks of the brush. The tick draws itself with stroke-dashoffset when the brush is halfway.

The colour of red hot clay

At the start a table is computed every 10 degrees: Planck’s law from 380 to 780 nanometres, weighed by the CIE 1931 curves (the analytic fit of Wyman, Sloan and Shirley), taken to linear sRGB and normalised. Then it is looked at as through a spy hole: an exposure that grows with the luminance, and each channel saturating on its own (1 − e^(−c·E)), plus a little glare at the top; so under 525 degrees nothing shows, at 700 it is cherry and at the top the saturated red lets the green climb to a light yellow. The glow is a layer in mix-blend-mode screen over the slab already darkened, that is light that adds up, with a radial gradient between the edge and a middle that has a temperature of its own and chases it late. Near the top a layer of light patches in screen drifts slowly and breathes with two sines, because a kiln’s light is never a flat colour.

The kiln, in one timeline

One GSAP timeline, a little over two seconds: the surroundings go dark, the temperature climbs in HEAT seconds (the dark part quickly, then red, orange and yellow a little faster towards the top) and meanwhile the slab shrinks by SHRINK with a scale on the whole of it, like clay: the tile is laid out as wide and as tall as the form, so nothing reflows. That is why at the top a veil the colour of the glowing clay is enough for a tenth of a second, while under it the form becomes the tile; after SOAK seconds the temperature falls in COOL seconds, fast at first like anything hot, and the door opens again at the last red: the tile can be read. The highlight and the last degrees come after. With reduced motion the slab keeps its size and only the colours dissolve. A click from a script (detail 0, the preview) makes one move at a time without taking the focus, with a drawn caret: the first fills the form in right (the catalogue’s picture), the second sends it to the kiln; in the rounds after, a new name, the wrong email, the fix and the choices, with another glaze.

Values to change

NameFileDefaultWhat it changes
PEAKscript.js1240The temperature at the top of the firing, in degrees: 1240 is stoneware; a lower firing stays redder.
HEATscript.js1.1How many seconds the kiln takes to climb to the top.
SOAKscript.js0.2How many seconds the kiln holds the top: the form becomes the tile in the first tenth.
COOLscript.js1.4How many seconds it takes to cool down: the tile can be read after a third of it.
SHRINKscript.js0.12How much the slab shrinks in the kiln, like clay: 0.12 is twelve per cent.
BRUSHscript.js0.6How many seconds the brush takes to glaze a field that is right.
SETTLEscript.js0.6The seconds of quiet after the last key before the field reads itself over.

Try them in the Playground

When to use it

When booking a class, a workshop or a visit, where the form is short and the confirmation should stay in mind: the change on sending is the moment the person signing up knows it is done. The checking suits any form: it waits for the typing to stop, does not shout while you type and goes as soon as the field is right. The kiln and the glaze are the theme of a pottery; for another product keep the brush and the change under the veil and change the colours.

On phones

The slab takes the width of the screen (358 pixels on a 390 phone) and is about as tall as the screen; the fields are 48 tall, the tiles 56 and 64, the button 52, all over the 44 of a finger. The fields’ text is at 16 pixels, so Safari does not zoom the page on a tap; the email opens the keyboard with the @; the Enter key says Next in the name and moves on to the email, and Send in the email. The tiles are chosen with a tap and the hover only applies where there is a pointer. The tile comes out 315 wide and its lines wrap by themselves.

With reduced motion

The brush does not run: the glaze and the tick fade in. Wrong fields do not wobble, the lines underneath swap with a fade and the button’s words cross without moving. In the kiln only the colours stay, with the same timing: the dark, the glow and the veil dissolve into one another, the slab does not shrink, the patches of light stay still and the highlight on the tile does not run. Book another seat dissolves the tile into the new form.

Pitfalls

  • The first firing lasted over five seconds, with the form gone in a flat cream rectangle for more than half a second: for the person booking it was a wait, and it read as a flash. Now a little over two seconds pass from the click to a tile that can be read, all the colours stay, and the veil covers for a tenth of a second with the light stronger at the edges and patches that move.
  • To hide behind a veil that short nothing must reflow under it: the slab narrowed by changing its width and height, and the narrower tile wrapped while it did. Now the tile is laid out as big as the form and the slab shrinks with a scale, as clay does; the tile’s words are a little bigger so they come back to the right size once shrunk.
  • A veil in solid colour over the glow in screen made a small dark patch in the middle right at the swap: the glow lightens, the veil covers. Now the veil has the colour of the glowing clay, that is the glow already added to the clay in the dark of the kiln.
  • The black body colour alone is wrong for a kiln: at 1,240 degrees Planck’s law gives a full orange, but through the spy hole it looks yellow white. The yellow white is the eye, or the camera, saturating: each channel is now exposed on its own with 1 − e^(−c·E) and the red, saturating first, lets the green and a little blue climb.
  • The veil that covers the form at the top took its colour from a CSS variable written on the glow layer, which is its sibling and not its parent: it was transparent and the form could be seen turning into the tile. The variables now sit on the slab, which passes them to both.
  • The middle of the slab followed the edge with a fixed gap, 150 degrees less going up and 90 more coming down: when the kiln turned, the middle jumped by 240 degrees, and it showed. Now the middle has a temperature of its own that chases the edge’s with a delay, up and down.
  • The halo was a box-shadow whose blur grew on every frame: in pictures taken while the slab shrank a hard line was left where the blur had not been redrawn. Now the blur is fixed and only the colour and the alpha change, which also costs less.
  • The error line of a field being corrected changed at every key (.ne, then .n, then right) and flickered: a red field turns right at once, but the words of its error wait for a pause.
  • The button’s background, absolutely positioned, took the text’s grid-area and started after the left padding: it stuck out 20 pixels on the right. The grid rule now applies to every child but the background.
  • The inner shadow of a chosen tile, made with box-shadow inset, ended up under the glaze, which is a child: the cobalt and the red edges now sit in an ::after above the glaze, and so does the depth of the well.
  • The button’s words rolling over to Firing sat on each other for a moment: now the first leaves completely before the second comes in.
  • With Book another seat the tile went in one frame and the slab jumped from celadon green to clay: now the tile dissolves into the clay and only then does the slab open out for the new form.

Libraries

GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Bricolage Grotesque (font variabile) 5.3.0.

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

Testing

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