Skip to content
animorio
IT
All components

The email field

Forms, Text, SVGGSAPAdvancedCompressed weight: Demo 16 KBGSAP 28 KBFreeDownload the zip

The email field of a sign-up that reads the address like a proofreader: while you type it offers the rest of the provider in grey, and a typo like nora@gmial.con gets a blue wavy line and a suggestion; taken, the letters correct themselves in place, the wrong one jumps out and falls, the right one drops in from above and the two swapped ones leap over each other. If something is missing the red pencil comes, with an insertion mark where it goes.

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 email field</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">
    <!-- the email field of a newsletter sign-up that reads the address like a copy editor: the rest of a known
         provider in grey while typing, a blue wavy line under a likely typo and the letters that fix themselves when
         the suggestion is taken, the red pencil where something is missing, and the button that sends it -->
    <form class="mail" action="#" novalidate data-mail data-autoclic>
      <label class="mail__label" for="mail-input">Email address</label>
      <div class="mail__field" data-field>
        <input class="mail__input" id="mail-input" name="email" type="text" inputmode="email" autocomplete="email" autocapitalize="off" autocorrect="off" spellcheck="false" enterkeyhint="send" placeholder="name@example.com" aria-describedby="mail-note" aria-invalid="false" data-input>
        <div class="mail__ink" aria-hidden="true" data-ink>
          <div class="mail__row" data-row>
            <svg class="mail__marks" data-marks><path class="mail__squiggle" data-squiggle/><path class="mail__wedge" d="M-4.6 5.4 0 0l4.6 5.4" data-wedge/></svg>
            <span class="mail__ghost" data-ghost><span class="ghost__clip" data-ghost-clip><span class="ghost__text" data-ghost-text></span></span><span class="ghost__key">tab</span></span>
            <span class="mail__caret" data-caret></span>
          </div>
        </div>
        <svg class="mail__tick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.6 10.4l3.6 3.6 7.2-8"/></svg>
        <button class="send" type="submit" data-send>
          <span class="send__bg" data-send-bg></span>
          <span class="send__label" data-send-label>Subscribe</span>
          <svg class="send__spin" viewBox="0 0 24 24" aria-hidden="true" data-spin><circle cx="12" cy="12" r="8.5"/></svg>
          <svg class="send__done" viewBox="0 0 24 24" aria-hidden="true" data-done><path d="M6.2 12.6l3.9 3.9 7.8-8.9"/></svg>
        </button>
      </div>
      <div class="mail__note" id="mail-note" aria-live="polite" data-note><span class="note__line is-help"><span class="note__words">One letter on Sundays. Leave whenever you like.</span></span></div>
      <span class="sr" aria-live="polite" data-live></span>
    </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.

58 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 email field” from Animorio and fit it into my site

What it does

On a black background the words Email address, a graphite field with rounded corners with the light Subscribe button inside it on the right, and under it the line One letter on Sundays. Leave whenever you like. Tapped, the field’s edge brightens with a halo. Typing after the @, the rest of a known provider shows in grey after the caret, with a drawn tab key beside it: Tab, the right arrow or a tap on the grey letters takes it, and the grey letters ink in one after the other with a little hop. If the provider changes (sam@h offers hotmail.com, sam@he offers hey.com) the grey part rolls over like a reel and the key comes back at the new end. A moment after the last key the field reads the address over. A likely typo, like nora@gmial.con, gets a blue wavy line that draws itself from the left, wriggling, under the domain, and under the field a pencil shows with Did you mean nora@gmail.com?, the letters to change in blue. Tapping the suggestion (or with Tab) the wavy line pulls into a straight line and goes, and the letters correct themselves in place: the wrong n turns red, hops and falls out through the bottom of the field turning, the right m drops in from above with a bounce, the i and the a swap by leaping over each other, one high and one low, and the others slide to make room; the new letters stay blue for a moment, then turn white. Then a green tick draws itself next to the address and That looks right shows below. If something is missing or wrong the edge turns red, the field shakes and the message comes up below with a triangle: Add the ending, like .com, with a red insertion mark springing up under the place where it goes, or An email can’t have spaces in it with the red wavy line under the space; as soon as the address is right again the error goes by itself. Pressing Subscribe the word leaves upwards, the button narrows into a circle with a spinning arc and then turns green with a tick, while You’re in. The first letter comes on Sunday. shows below and the address dims to grey.

How it works

A real field, of type text

The input is real (a label, autocomplete email, inputmode email for the keyboard with the @ on phones, aria-invalid and aria-describedby pointing at the line underneath, which is aria-live). It is of type text, not email: an email input does not let the script read or move the caret (selectionStart is null and setSelectionRange throws), and here it matters whether the caret is at the end. Its own letters are the ones you see: the drawn letters only take their place while they move, and meanwhile the input’s text, caret and placeholder are transparent.

Where each letter sits

Every position is measured with measureText on a canvas, in the input’s font read from getComputedStyle. A letter starts where the text up to and including it ends, less its own width: that way the kerning with the letter before (W and a, y and the dot) counts, as the input counts it. Everything drawn sits in a row shifted by the input’s scroll (scrollLeft, read on every frame only while the field has the focus), inside a layer cut exactly to the input’s text box.

The rest of the provider, and the typo

After the @, with the caret at the end, the first provider in PROVIDERS that starts with the domain typed shows in grey after the caret; when the provider changes the old ending leaves upwards and the new one comes in from below, like a reel. PAUSE seconds after the last key (a GSAP delayedCall restarted at every key) the domain is compared with the providers using the Damerau-Levenshtein distance: one letter for the short ones, two for those of nine letters or more, with a length differing by one letter at most. If none is close, the ending is compared with ENDINGS (.con becomes .com). The wavy line is an SVG path recomputed on every frame while it draws: a sine wave whose amplitude settles with elastic.out.

The letters that correct themselves

The same Damerau-Levenshtein table, walked back from its corner, gives the list of steps: letters that stay, that are replaced, that go, that come, and swapped pairs. Those that stay slide to their new place with power3.inOut; in a swapped pair one leaps HOP pixels growing and the other passes underneath shrinking, on an arc made with a sine; those that go fall on a real parabola (a push upwards and gravity), turning and fading; the new ones drop in with back.out. It all takes FIX seconds; if a long address has to scroll, the row glides along with the letters.

Errors, sending and the preview

The check says what is missing and where: a red wavy line under the wrong part, or an insertion mark under the place where something has to be written (the @ before gmail.com, the ending after the domain). It checks on leaving the field and on sending; after an error, at every key, and the error goes as soon as the address is right. Sending narrows the button into a circle (width and radius with GSAP) with an arc spinning for WAIT seconds. A click from a script on the form (detail 0, the library’s preview) makes one move at a time without taking the focus, with a drawn caret: a typo, the fix, sending, a provider completed, an ending forgotten and added.

Values to change

NameFileDefaultWhat it changes
PAUSEscript.js0.7The seconds of quiet after the last key before the field reads the address over.
FIXscript.js0.85How many seconds the letters take to correct a typo.
HOPscript.js15How high a letter leaps over its neighbour when the two swap places, in pixels.
WAVEscript.js1.6How wavy the line under a word is, in pixels.
WAITscript.js1.3How many seconds the subscription takes in the demo, while the arc spins.
PROVIDERSscript.js['gmail.com', 'yahoo.com', 'outlook.com', …]The providers the field completes and checks typos against, the most common first.
ENDINGSscript.js['com', 'net', 'org', …]The endings the field knows, to notice a .con or a .cmo.

Try them in the Playground

When to use it

In a newsletter sign-up, when registering for a service, at a shop’s checkout: anywhere a wrong address means a lost person, because the confirmation will never reach them. The suggestion does not block: whoever really meant that address can send it anyway.

On phones

The field takes the width of the screen (358 pixels on a 390 phone), stays 60 tall and the button narrows to 108. A tap opens the email keyboard, with the @ and the dot, and the Enter key says Send. The grey rest of the provider is taken by tapping it, without the keyboard closing; the suggestion is tapped like a button. An address longer than the field scrolls, and the letters and marks scroll with it. Tapping Subscribe with a typo just found shows the suggestion instead of sending at once.

With reduced motion

The letters do not leap or fall: the old address fades where it is and the corrected one appears. The wavy line and the insertion mark fade in, without wriggling or springing up; the grey ending changes without rolling; the field does not shake; the button does not narrow and the arc stays still; the lines under the field swap with a fade.

Pitfalls

  • With type email the field does not say where the caret is (selectionStart is null) and setSelectionRange throws: the field is of type text with inputmode email, which on phones gives the same keyboard.
  • The drawn letters, placed at the width of the text before them, landed up to two pixels to the right of the real ones after a kerned pair (the a after the W, the dot after the y): the kerning between two letters only counts when they are measured together. Now each letter starts where the text up to and including it ends, less its own width, and matches to a hundredth of a pixel.
  • Becoming visible again, the input’s text faded in from transparent (a colour transition left there for the sent state) and for a moment the address looked grey: the transition now only applies to the sent state.
  • A long address corrected by a script stayed cut at its end: the browser does not always scroll to a caret put there by a script. The scroll is taken to the end by hand, and the row of drawn letters glides along with it.
  • While the provider changed, the tab key, which followed the end of the grey text, waited for the old ending to go and then jumped; sliding it, it passed over the text going out. Now the old ending leaves the flow and the key fades out and back in at the new end.
  • Two lines under the field sat on each other while one went out and the other came in: the new one only comes in once the old one has gone.
  • With a finger the button does not take the focus: leaving the field to send, the suggestion appeared and the sending went ahead at once, with the typo. Now a suggestion that has just come up stops the sending, and lets it through only once it has been on screen long enough to be read.
  • The spinner and the tick sat to the right of the circle: the button’s grid column was as wide as the hidden word Subscribe. The column is now minmax(0, 1fr).

Libraries

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

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

Testing

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