Skip to content
animorio
IT
All components

The enamel avatar

Avatars, Transitions, SVGGSAP, CanvasAdvancedCompressed weight: Demo 19 KBGSAP 28 KBFreeDownload the zip

The profile avatar of a hiking club's app, made like a cloisonné pin: gold wires bent into a drawing and enamels in the cells between them. Choosing another animal the enamels drain away, the gold wires lift, bend and slide into the new drawing and the new enamels run in from above cell by cell, still raw: pale, grainy, matte. Saving is the firing: the token glows from the rim inward and shimmers in the heat, the powder melts into glass, it cools from the rim and comes out glossy, with a polish that passes like a reflection.

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 enamel avatar</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/lexend@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the avatar of a hiking club's app, made like a cloisonné pin in a round recess of the profile card.
         Each choice drains the enamels, bends the gold wires into the new drawing and runs the new enamels into
         its cells, still wet and matte; saving fires the token in the kiln, and it cools glossy. The token is
         drawn on the canvas; the choices under it are real radio buttons -->
    <section class="card" aria-label="Your avatar" data-card data-autoclic>
      <div class="card__coin">
        <span class="card__slot" aria-hidden="true"></span>
        <canvas class="card__canvas" aria-hidden="true" data-canvas></canvas>
        <button class="card__token" type="button" tabindex="-1" aria-label="Edit avatar" data-token></button>
      </div>

      <div class="card__body">
        <div class="rest" data-rest>
          <h2 class="rest__name">Maya Lindqvist</h2>
          <p class="rest__meta">@maya.lind · Trail crew</p>
          <button class="btn btn--line" type="button" data-edit>Edit avatar</button>
        </div>

        <form class="editor" data-editor>
          <fieldset class="editor__row" data-who>
            <legend class="sr">Picture</legend>
          </fieldset>
          <fieldset class="editor__row" data-tint>
            <legend class="sr">Colour</legend>
          </fieldset>
          <div class="editor__actions">
            <button class="btn btn--soft" type="button" data-cancel>Cancel</button>
            <button class="btn btn--ink" type="submit" data-save>
              <svg class="btn__tick" viewBox="0 0 24 24" aria-hidden="true" data-tick><path d="M5.5 12.6l4.1 4.1L18.6 7.4"/></svg>
              <span class="btn__label" data-save-text>Save</span>
            </button>
          </div>
        </form>
      </div>

      <p class="sr" aria-live="polite" data-live></p>
    </section>
  </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 enamel avatar” from Animorio and fit it into my site

What it does

On a white background a white card with a round recess and, in it, a token 120 pixels wide made like a cloisonné pin: an enamel fox on a pine green field, with gold wires between the enamels and a gold rim. Under it are Maya Lindqvist, @maya.lind · Trail crew and the Edit avatar button. When the page opens the token is made in front of you: first the bare gold base, then the wires lying down and drawing the fox, then the enamels running in from above, the green of the field and then the cells one after the other. With the mouse over it, the light on the enamel and on the gold moves towards the pointer, as when a pin is turned under a lamp. Edit avatar (or the token) opens the choices: six small tokens (the initials ML in a gold ring and five animals: fox, owl, bear, frog, cat), six enamel colours, Cancel and Save. Choosing another animal the fox's enamels drain away, going back up the way they came in; the gold wires lift, with a small shadow under them, and bend and slide into the new drawing, the bend running along each wire; when they lie down, the new enamels run in from above and fill the cells one after the other, each with its wet front wavering. Enamel just laid is raw: paler, matte and grainy, without the gloss of glass. A new colour runs into the field over the old one, and along the small tokens too. A click on the token, with the choices open, picks an animal and a colour at random. Save is the firing: the button says Saving…, the token glows from the rim inward, dull red, then orange, the gold wires shine brighter, the kiln's light spreads on the card and the token shimmers in the heat; meanwhile the powder melts into glass. When the save comes back it cools, the rim first and the middle last, comes out with full, glossy colours and a polish passes along the diagonal lighting up the gold: the button says Saved with a drawn tick and the card goes back to the name. Cancel puts back the saved avatar, already fired. The initials are gold on the dark enamels and dark enamel edged in gold on the light ones.

How it works

Wires and cells from one drawing

Each illustration is written once, as SVG paths: the cells with their enamel (the walls) and the wires on their own. At start every wall becomes a loop of 64 evenly spaced points, taken with getPointAtLength from a hidden path of the page; an open wire becomes a loop that goes along it and comes back. Every cell knows where the enamel reaches it (its point nearest to a point above the token) and how far it has to run to fill.

The true cells

A cell shows only where no later cell lies over it: it is clipped by its path and then, for each later walled cell that touches it, by «everything but that cell» (a big square with the path in it, even-odd). Successive clips intersect, so the subtraction is exact; the wires lying down are hidden the same way. The glints in the eyes have no wall and are laid on top.

The wires bending

Between two drawings the loops are paired by place and size, the closest pairs first; the new loop is turned (and reversed if needs be) so that its points line up with the old ones with the least travel. The points move with power3.inOut, but each starts a little after the one before (LAG), so the bend runs along the wire, in BEND seconds. Lifted, the wires cast a small shadow and are seen whole; lying down they cross-fade to the clipped version. A wire with no partner shrinks into its middle and fades, a new one grows out of its own.

The enamel running

The old enamels drain back towards the point they came in from; the new ones run in from above: each cell starts when the flow reaches it (its distance from the top over FLOW) and fills with a blot growing from its entry point, its edge wavering on two sines with a light rim like a wet edge. Enamel just laid is raw powder: paler, matte, with a fine grain of light and dark specks (GRAIN) and no gloss. A new colour runs into the field over the old one.

The firing

Save heats the token in FIRE[0] seconds: the heat comes in from the rim (a radial gradient of eleven stops, each with the heat at its radius, from dull red to the kiln's orange), the gold wires shine with a 'lighter' stroke, the light spreads on the card and the token shimmers, redrawn in 2-pixel strips pushed sideways by two sines; meanwhile the powder melts into glass. It stays hot until the save comes back (here a pretend one of SAVING seconds), then cools in FIRE[1] seconds from the rim to the middle, and a band of light runs along the diagonal lighting up the gold.

Real choices, keys and the preview

Animals and colours are real radio buttons with their aria-label in two fieldsets; Edit avatar takes the keys onto the chosen animal, the arrows change the choice, Escape cancels, on closing the focus goes back to Edit avatar, and an aria-live line says when the avatar is being saved, is saved or the changes are discarded. Going back to the saved avatar, what is still raw goes back to fired. Everything runs on GSAP's ticker only while something moves. A click from a script (the library's preview) tells a little story: it opens, chooses, saves, and again with other choices.

Values to change

NameFileDefaultWhat it changes
INITIALSscript.js'ML'The letters on the token when no animal is chosen (the first two).
COLOURSscript.js[['Midnight', '#24335c'], …]The enamel colours of the field: name and colour.
SAVEDscript.js[1, 1]The avatar saved when the page opens: the animal (0 = the initials) and the colour.
BENDscript.js0.5The seconds the gold wires take to bend into a new drawing.
FLOWscript.js170How fast the wet enamel runs into the cells, in hundredths of the token a second.
GRAINscript.js0.4How grainy and matte the enamel looks before it is fired (0 = smooth).
FIREscript.js[0.7, 1.1]The kiln when saving: the seconds it takes to heat up and to cool down.
SAVINGscript.js0.9How long the pretend save takes, in seconds (in a real app, as long as the request).

Try them in the Playground

When to use it

For the profile of an app or a community, choosing the avatar in a chat, a game or a club, the account settings of a service with illustrated avatars, a badge to collect, and in general for a draft that becomes final when it is saved.

On phones

The card is 352 pixels wide (less on a narrower screen) and 330 tall, and the six small tokens and six colours fit at 390 (on an even narrower screen they get a little smaller). Everything works by touch: a tap on the token opens the choices, or picks one at random with the choices open; the light that follows the mouse only moves to the spot touched on a phone.

With reduced motion

No wires bending, no enamel running, no shimmer and no polish running across: the new face fades in over the old one, the token is there already made and the firing is an orange glow that fades in and out. Raw and fired still show, the light does not follow the pointer and the choices swap with the name with a fade.

Pitfalls

  • Drawing all the wires over all the enamels showed the bits hidden under later cells (the base of the fox's ears crossed its head): a wire lying down is clipped like its cell, minus the later cells; a lifted wire is seen whole, and the two versions cross-fade as it lies down.
  • Filling each cell in its whole path made the head's orange run over the cheeks before the white came, and taking it away afterwards was a jump: each cell is clipped to its true part, its path minus the later walled cells, with even-odd clips one after the other.
  • Draining towards the bottom of the cell and running in from above were two different points: a choice in the middle of a pour made the enamel jump. Now the enamel drains back towards the point it came in from, so it can turn round at any moment.
  • Wires that go away shrink to a point, and a wire of zero length with round caps is a gold dot: they fade out twice as fast as they shrink.
  • Going back to the saved avatar after some changes, Save had nothing to save and the token stayed raw: when the draft is the saved avatar again (by choosing or with Cancel), whatever is still raw goes back to its fired look, piece by piece.
  • The first grain was made of bright specks and looked like glitter enamel: raw enamel is chalky, a paler colour and a fine grain of faint specks, one per pixel, in the canvas's pixels.
  • The heat front made a dark ring where the glow was weak: the glow's opacity grows with the heat to the power of 1.3, and its weakest colour is a warm red, not black.
  • The canvas reads the gold and the glow from :root, but the Playground changes the variables live: a MutationObserver on the root's style reads the colours again and redraws, and the small tokens use var(--gold) in their style, so three colours are enough for a silver token.
  • The card's video starts about 0.9 seconds after the page opens: the token is made in 1.6 seconds, so the video finds it already made, and its two clicks show a change and the whole firing.

Libraries

GSAP 3.15.0, Lexend (font variabile) 5.3.0.

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

Testing

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