Skip to content
animorio
IT
All components

The like button

Buttons, SVG, TransitionsGSAPMediumCompressed weight: Demo 4.7 KBGSAP 28 KBFreeDownload the zip

A heart and a count: pressed, the heart squashes, a pink ripple opens around it, the heart comes back full and red with a bounce while eight short rays fly off, and the count rolls up by one; pressed again it empties and the count rolls back.

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 like button</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/plus-jakarta-sans@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the button: a heart and a count. A press squashes the heart, a ring opens around it, the heart comes back
         full with a bounce while short rays fly out, and the count rolls to its next number; another press empties
         it and the count rolls back -->
    <button class="like" type="button" aria-pressed="false" data-like data-autoclic>
      <span class="like__icon" aria-hidden="true">
        <svg class="like__burst" viewBox="-60 -60 120 120" data-burst>
          <circle class="like__ring" r="0" data-ring/>
          <g data-rays></g>
        </svg>
        <svg class="like__heart" viewBox="0 0 32 32" data-heart>
          <path class="like__outline" data-outline d="M16 27.6c-.5 0-1-.2-1.4-.5C8.9 22.6 3.6 18.1 3.6 11.9c0-3.8 2.9-6.6 6.4-6.6 2.5 0 4.6 1.3 6 3.3 1.4-2 3.5-3.3 6-3.3 3.5 0 6.4 2.8 6.4 6.6 0 6.2-5.3 10.7-11 15.2-.4.3-.9.5-1.4.5z"/>
          <path class="like__fill" data-fill d="M16 27.6c-.5 0-1-.2-1.4-.5C8.9 22.6 3.6 18.1 3.6 11.9c0-3.8 2.9-6.6 6.4-6.6 2.5 0 4.6 1.3 6 3.3 1.4-2 3.5-3.3 6-3.3 3.5 0 6.4 2.8 6.4 6.6 0 6.2-5.3 10.7-11 15.2-.4.3-.9.5-1.4.5z"/>
        </svg>
      </span>
      <span class="like__count" aria-hidden="true" data-count></span>
    </button>
  </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.

13 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 like button” from Animorio and fit it into my site

What it does

On a white background a white pill with an empty heart and the number 1,284. Under the mouse the heart beats once. Pressing, the pill sinks a little and comes back on a spring; the heart squashes for a blink, then a pink ripple opens from behind it and thins out until it is gone, the heart comes back full and red with an elastic bounce, and further out eight short rays, red, coral and amber, fly off and fade. Meanwhile the number turns red and rolls to 1,285: the old figure leaves at the top and the new one comes in from below, as in a counter, and only the figures that change move. The pill takes a pinkish background. Pressing again the heart empties with a little jolt and the number rolls back. When the page opens the pill rises and the heart beats once.

How it works

The heart

Two SVG paths with the same shape: the outline, which turns red with a CSS transition, and the full heart, which goes from scale 0 to 1 around a point just below the centre. Pressing, the whole heart goes to 0.76 in a tenth of a second, then back to 1 with the fill growing from 0.15, both with elastic.out(POP).

The ripple and the rays

Behind the heart sits a second, bigger SVG: a circle whose radius goes from 11 to 26 while its stroke goes from 7 to nothing, in a little more than half of BURST, and eight lines, each in a rotated group. Each ray first grows outwards starting 24 units from the centre, then shrinks towards its far tip; every other one is shorter. It shows up as it grows and vanishes as it shrinks, so its round ends are never left alone as a dot.

The count

Each figure sits in a slot that cuts what sticks out. When it changes, the new figure comes in below the old one and they go up together by a whole height (plus the slot’s padding) with back.out, in ROLL seconds; taking the like back they go down. If the number changes length (from 999 to 1,000) it rolls all at once. The number is written with Intl.NumberFormat, with the thousands comma.

Press and keyboard

The pill sinks on pointerdown and comes back on a spring on pointerup. It is a real button with aria-pressed, and its name also says the number (“Like, 1,285 likes”), so the keyboard and screen readers get everything.

Values to change

NameFileDefaultWhat it changes
COUNTscript.js1284The count before your like.
RAYSscript.js8How many rays fly off.
BURSTscript.js0.6The seconds of the ripple and the rays.
POPscript.js[1, 0.4]The spring of the heart filling up: its strength and how quickly it settles.
ROLLscript.js0.5The seconds a figure takes to roll.
COLORSscript.js['#ff2f55', '#ff8a5c', '#ffc247']The colours of the rays, in turn.

Try them in the Playground

When to use it

For a like, a save, a favourite or a vote: wherever a click says you like something and a number counts how many have said so.

On phones

Taps work like clicks. The heartbeat under the mouse is not there with a finger; everything else is.

With reduced motion

The heart fills and empties without squashing or bouncing, just with a short fade; no ripple, no rays, the number changes at once and the pill does not sink.

Pitfalls

  • A line as long as nothing with round ends is drawn as a dot: at rest the rays are hidden, and they appear and disappear while their length changes.
  • The circle’s stroke width is set in the CSS, which beats the SVG attribute: to grow it, it must be animated as a style (strokeWidth), not as an attribute.
  • The rays’ fromTo has immediateRender: false: without it their starting state would show at once on the click, before their turn.
  • A figure still rolling when another one arrives ends at once: only the newest stays in the slot, so pressing quickly the figures never pile up.

Libraries

GSAP 3.15.0, Plus Jakarta Sans (font variabile) 5.3.0.

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

Testing

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