Skip to content
animorio
IT
All components

The signature pad

Drawing, Transitions, TextGSAPAdvancedCompressed weight: Demo 8.2 KBGSAP 28 KBFreeDownload the zip

A sheet to sign: the ink follows the pen and thins when it goes fast, comes out a wet blue and dries dark; Undo winds the last stroke back to where it began, Done brings a stamp down on it, and the name can also be typed, coming out handwritten.

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 signature pad</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/literata@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/caveat@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the signature pad: the ink thins with speed and dries from blue to dark, Undo winds the last stroke back, Done
         stamps the sheet; the name can also be typed, and comes out handwritten -->
    <section class="sign" aria-labelledby="sign-title" data-sign data-autoclic>
      <header class="sign__head">
        <h2 class="sign__title" id="sign-title">Sign the agreement</h2>
        <p class="sign__note">Villa Rosa · 3 nights from 14 October</p>
      </header>
      <div class="sign__tabs" role="tablist" aria-label="How to sign">
        <button class="tab" type="button" role="tab" aria-selected="true" aria-controls="sign-pad" id="tab-draw" data-tab="draw">Draw</button>
        <button class="tab" type="button" role="tab" aria-selected="false" aria-controls="sign-pad" id="tab-type" data-tab="type" tabindex="-1">Type</button>
        <span class="tab__mark" aria-hidden="true" data-mark></span>
      </div>
      <div class="pad" id="sign-pad" role="tabpanel" aria-labelledby="tab-draw" data-pad>
        <canvas class="pad__ink" role="img" aria-label="No signature yet" data-canvas></canvas>
        <p class="pad__typed" aria-hidden="true" data-typed></p>
        <span class="pad__hint" aria-hidden="true" data-hint>Sign here</span>
        <svg class="pad__cross" viewBox="0 0 20 20" aria-hidden="true"><path d="M5 5l10 10M15 5L5 15"/></svg>
        <span class="pad__line" aria-hidden="true"></span>
        <div class="pad__stamp" aria-hidden="true" data-stamp><span>Signed</span><small data-date></small></div>
        <svg class="pad__nib" viewBox="0 0 40 40" aria-hidden="true" data-nib><path d="M20 38 L13 24 L17 6 Q20 2 23 6 L27 24 Z"/><path d="M20 38 L20 25"/></svg>
      </div>
      <label class="sign__type" hidden data-type-row>
        <span class="sr">Your full name</span>
        <input class="sign__input" type="text" placeholder="Type your full name" autocomplete="name" maxlength="28" data-input>
      </label>
      <div class="sign__actions">
        <button class="btn" type="button" data-undo disabled>Undo</button>
        <button class="btn" type="button" data-clear disabled>Clear</button>
        <button class="btn btn--main" type="button" data-done disabled>Done</button>
      </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.

24 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 signature pad” from Animorio and fit it into my site

What it does

On a black background a paper-coloured sheet with Sign the agreement and Villa Rosa · 3 nights from 14 October; under it, two tabs, Draw and Type, with a white pill under the one chosen, the signature box with a small cross, a dashed line and Sign here, and the buttons Undo, Clear and Done. Drawing with a finger, the mouse or a pen, the ink follows the hand and thins where the hand goes fast; it comes out a bright wet blue and in a little under a second dries to an almost black blue. With a mouse a nib follows the pointer on the sheet, leaning a little with the movement and dipping as it writes. Undo winds the last stroke backwards to the point where it began; Clear winds all the strokes back, from the last to the first. Done brings a red stamp down on the sheet, Signed with the day’s date, which arrives big and tilted, lands with a thump and makes the sheet jump; the button becomes Sign again. In Type the name written in the box appears handwritten on the line, each new letter landing with a little turn.

How it works

The ink

Every stroke is a list of points with their widths: the speed between two points (pixels a millisecond) takes the width from WIDTH[1] towards WIDTH[0] as it nears SPEED, and each point moves only a little towards the new width, so the line does not jump. It is drawn on a canvas with curves through the middle points (quadraticCurveTo), each piece as thick as its two ends; the pointer also gives the points gathered between two frames (getCoalescedEvents).

Wet and dry

Every stroke has its own drying state, from 0 to 1 in DRY seconds from the end of the stroke: its colour is the blend of the sheet’s two colours (--wet and --ink, read from the CSS) by that state.

Winding back

A stroke remembers how many of its points show: Undo takes that number to zero in REWIND seconds with power2.in, so the stroke draws back from its end to its start, then removes it; Clear does the same with all of them, the last first and slightly overlapping.

The stamp and the typed name

The stamp starts STAMP times bigger and more tilted and comes down onto the sheet in 0.32 seconds with power3.in, then the sheet jumps (keyframes on y and scale) and the stamp swells for a moment. The typed name is in the Caveat font: the letters already written stay, the new ones arrive small, turned and a little lower and settle with back.out.

Keys and the preview

Draw and Type are tabs (role tablist, the arrows go from one to the other) and Type is the way to sign without drawing: someone on the keys types the name and signs with Enter. The canvas says whether there is a signature (role img) and an aria-live region says Signed or that the sheet was cleared. A click from a script (the library’s preview) signs with a pretend pen, whose nib shows, then stamps the sheet and finally clears it.

Values to change

NameFileDefaultWhat it changes
WIDTHscript.js[1.2, 4.4]The thinnest and the thickest the ink gets, in pixels: fast is thin.
SPEEDscript.js2.2The speed, in pixels a millisecond, at which the ink is at its thinnest.
DRYscript.js0.8The seconds the ink takes to dry from wet blue to its dark colour.
REWINDscript.js0.4The seconds a stroke takes to wind itself back with Undo.
STAMPscript.js2.2How big the stamp is when it starts coming down onto the sheet.

Try them in the Playground

When to use it

For signing a rental agreement, a consent form, a delivery, an accepted quote, the check-in at a guesthouse; or for a freehand drawing inside a form.

On phones

You sign with a finger without scrolling the page (touch-action none on the sheet); there is no nib, as under a finger it would not help; the name box is 16 pixels, so Safari on iPhone does not zoom the page.

With reduced motion

The ink comes out already dry, Undo and Clear remove the strokes without winding them back, the stamp appears in its place without dropping or shaking the sheet, and the name’s letters appear without turning.

Pitfalls

  • A stroke of varying width cannot be one path: each piece between two middle points is a path of its own with its own width, and the round ends hide the joins.
  • The canvas must be drawn at the screen’s density (up to 2) and brought back to the CSS size with setTransform, or the signature comes out blurred.
  • Disabling the box that has the focus leaves it on the page: it is handed to the button first.
  • The nib takes the cursor’s place only with a mouse ((hover: hover) and (pointer: fine)): under a finger a drawn cursor would end up beneath the fingertip.

Libraries

GSAP 3.15.0, Literata (font variabile) 5.3.0, Caveat (font variabile) 5.3.0.

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

Testing

Tested on 3 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: Done

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