Skip to content
animorio
IT
All components

The scratch card

Cards, Physics, TransitionsGSAPAdvancedCompressed weight: Demo 6.8 KBGSAP 28 KBFreeDownload the zip

A ticket with a gift under silver foil: a coin scratches it away along its path and the flakes fall, spinning, with gravity; past half, the rest comes off by itself in a shower of flakes and the gift jumps out with a flash of light.

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 scratch card</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/chivo@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the scratch card: a coin scratches the foil away, flakes fall from it, and past half the rest comes off by
         itself and the gift jumps out -->
    <section class="gift" aria-labelledby="gift-title" data-gift data-autoclic>
      <h2 class="gift__title" id="gift-title">Your welcome gift</h2>
      <div class="ticket" data-ticket>
        <div class="ticket__prize" aria-hidden="true" data-prize>
          <p class="ticket__big" data-big></p>
          <p class="ticket__small" data-small></p>
          <div class="ticket__code">
            <span class="ticket__chip" data-code></span>
            <button class="ticket__copy" type="button" tabindex="-1" data-copy>Copy code</button>
          </div>
        </div>
        <canvas class="ticket__foil" aria-hidden="true" data-foil></canvas>
        <span class="ticket__coin" aria-hidden="true" data-coin></span>
      </div>
      <button class="gift__reveal" type="button" data-reveal>Reveal without scratching</button>
      <p class="sr" aria-live="polite" data-live></p>
    </section>
  </main>
  <canvas class="flakes" aria-hidden="true" data-flakes></canvas>

  <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.

16 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 scratch card” from Animorio and fit it into my site

What it does

On a white background Your welcome gift and a yellow ticket with notches at its sides, covered by silver foil with fine lines and SCRATCH HERE; under it, Reveal without scratching. With a mouse on the foil the cursor becomes a gold coin; dragging (or with a finger) the foil goes away along the path with a soft edge, and where the coin passes silver flakes come off, falling, turning over and fading, even outside the ticket. When more than half the foil is scratched, what is left comes off by itself in a shower of flakes and fades, and the gift jumps out one piece at a time: 20% OFF in red, over which a band of light runs, on your first stay, the code WELCOME20 and Copy code, which copies it and says Copied.

How it works

The foil

The foil is a canvas over the gift, painted with a silver sheen, diagonal lines and the words pressed in (light below and dark above). The coin takes it off with destination-out: a circle of radius BRUSH with a soft edge (a radial gradient), stamped along the path every third of the radius, so a quick stroke leaves no gaps.

How much is gone

Every 0.12 seconds of scratching the foil’s pixels are read (getImageData, with willReadFrequently) on a grid of 48 by 24 points: past REVEAL of clear points, the rest comes off by itself.

The flakes

At every touch of the coin FLAKES flakes come off: little silver rectangles with a push in the coin’s direction, a gravity (GRAVITY) and a spin, drawn on a canvas as big as the window; as they turn their width shrinks and grows (they show their edge) and they fade in a little under two seconds.

The gift

With the foil off (it fades and grows a little), the gift’s pieces arrive one after another from 0.7 with back.out, and a band of light runs over the big words: a gradient background clipped to the text (background-clip text) sliding from right to left.

Keys and the preview

Reveal without scratching shows the gift without scratching and takes the focus to Copy code; while the foil is there the gift is aria-hidden, then an aria-live region says it. Copy code copies the code to the clipboard. A click from a script (the library’s preview) scratches the foil in a zigzag with the coin until the gift comes out, and the next time puts the foil back like a sticker, from the left.

Values to change

NameFileDefaultWhat it changes
BRUSHscript.js22The radius, in pixels, of the coin that scratches the foil.
REVEALscript.js0.5How much of the foil must be scratched before the rest comes off by itself.
FLAKESscript.js2How many flakes of foil come off at each touch of the coin.
GRAVITYscript.js900How fast the flakes fall, in pixels a second squared.
PRIZEscript.js['20% off', 'on your first stay', 'WELCOME20']The gift: the big words, the small words and its code.

Try them in the Playground

When to use it

For a welcome voucher, a prize in a newsletter, the result of a contest, a surprise at the end of a purchase, a discount code to uncover.

On phones

You scratch with a finger without scrolling the page (touch-action none on the ticket) and without the long-press menu; there is no coin, as the finger is the coin; the foil is not repainted when Safari’s bars come and go.

With reduced motion

The foil still scratches off, but without flakes; past half it disappears at once and the gift appears without jumping and without the band of light, and the foil comes back without sliding.

Pitfalls

  • Reading a canvas’s pixels often (getImageData) is slow if the canvas lives on the graphics card: getContext('2d', { willReadFrequently: true }) keeps it where reading costs little.
  • On a phone the window changes height when the browser’s bars come and go: the foil is repainted only if its width changes, or the scratching would be lost.
  • A button hidden with display none makes what is above it jump on a centred page: here it goes with visibility hidden and keeps its room.
  • An eraser with a hard edge leaves steps along the path: a radial gradient from a solid centre to a clear edge gives a soft edge, like a real coin.
  • Safari clips at its edges the drop-shadow of an element whose children are transformed (the foil coming off): the ticket’s paper and its shadow sit on a layer of their own, a ::before with no children.

Libraries

GSAP 3.15.0, Chivo (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 6.8 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