Skip to content
animorio
IT
All components

The pricing switch

Pricing, Transitions, TextGSAPMediumCompressed weight: Demo 5.9 KBGSAP 28 KBFreeDownload the zip

Three plans and a switch between paying monthly and yearly: going yearly each old price is struck through and falls, the new lower one comes down into its place with a bounce and the line under it rolls over to the year’s total; the knob stretches as it runs, the chip with the months given away lights up and pops, and a ring of colour turns round the plan picked.

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 pricing switch</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/familjen-grotesk@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the pricing switch: from monthly to yearly the old price is struck through and falls, the new one comes down
         into its place, the yearly total opens under it, and the switch stretches as it runs -->
    <section class="plans" aria-labelledby="plans-title" data-plans data-autoclic>
      <header class="plans__head">
        <h2 class="plans__title" id="plans-title">Plans for every host</h2>
        <div class="bill" role="radiogroup" aria-label="Billing" data-bill>
          <button class="bill__opt" type="button" role="radio" aria-checked="true" data-period="month">Monthly</button>
          <span class="bill__track" aria-hidden="true"><span class="bill__knob" data-knob></span></span>
          <button class="bill__opt" type="button" role="radio" aria-checked="false" tabindex="-1" data-period="year">Yearly</button>
          <span class="bill__save" aria-hidden="true" data-save></span>
        </div>
      </header>
      <div class="cards" data-cards></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.

35 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 pricing switch” from Animorio and fit it into my site

What it does

On a black background, Plans for every host and a Monthly / Yearly switch with the chip 2 months free, unlit; under them three dark plans (Solo €12, Host €29, Group €79 a month), each with Billed every month, what is included with ticks and its button; Host is Our pick, with a green button and a green and light blue ring slowly turning round it. Going Yearly the knob runs to the other side stretching and squashing, and the chip turns green and pops out tilting like a sticker; in each plan a line strikes the price through, the price falls turning a little and the new one (€10, €24, €66) comes down from above with a bounce, one plan after another, while Billed every month drops away and the year’s total arrives in green (€288 billed once a year). Going back to Monthly the prices rise away and the old ones come back from below. A plan under the pointer lifts a little; coming in, the ticks draw themselves one after another.

How it works

The switch

The switch is a group of two choices (role radio) with a track between them that toggles them; the knob goes to x 22 in 0.42 seconds while keyframes stretch it to 1.4 and squash it to 0.86, like a running drop. The arrows change the choice and carry the focus.

The falling price

One timeline for each plan: going down, first a line strikes the price through (scaleX from 0 to 1), then the price falls and fades turning 6 degrees, the text changes and the new one comes down from above with back.out; going up, the old one rises away and the new one arrives from below. The plans start 0.06 seconds apart and SWAP sets the whole duration.

The rolling line

The line under the price is a slot 18 pixels tall with overflow hidden: the old words leave the same way as the price, change, and the new ones come in from the other side. So the plans never change height and nothing jumps.

The chip and the ring

The chip changes colour with a CSS transition and GSAP pops it from 0.7 to 1, tilting it 3 degrees. The plan picked (PICK) has a border made of a conic-gradient whose starting angle is a CSS variable, --turn, which GSAP takes from 0 to 360 degrees in RING seconds, forever.

Quick changes and the preview

Each plan keeps its timeline and kills it whole before starting a new one: killing only the tweens would leave alive the callbacks that write the text, which would write the old price late. A click from a script (the library’s preview) switches between monthly and yearly and every third time lifts a plan, as a pointer would.

Values to change

NameFileDefaultWhat it changes
PLANSscript.js[['Solo', 'One place to let', 12, […]], …]The plans: name, who it is for, price a month, what is in it.
FREE_MONTHSscript.js2The months a year given away to those paying yearly.
SWAPscript.js0.5The seconds a price takes to change.
PICKscript.js1The plan picked: 0, 1 or 2.
RINGscript.js6The seconds the ring of colour takes to go round the plan picked.

Try them in the Playground

When to use it

For the pricing page of a subscription service, an app or a piece of software, an agency’s packages, the rates of a gym or a coworking space.

On phones

The plans sit side by side and slide under the finger one at a time (scroll-snap), with the plan picked already in the middle and its neighbours peeking in at the sides; a tap does not lift the plans.

With reduced motion

The prices and the line under them change at once, without striking or falling; the knob and the chip go to their places without running or popping, the ring stays still and the ticks are already drawn.

Pitfalls

  • killTweensOf stops an element’s tweens but not the timeline holding them: its callbacks stay alive and, after a quick switch back and forth, would write the old price. Keep the timeline and kill it whole.
  • A line opening and closing under the price changes the plans’ height and, on a centred page, makes everything jump: better a fixed slot the words roll through.
  • In a grid with place-items center, a row of plans sliding sideways on a phone widens the column to its own width: the column has to be fixed with minmax(0, 1fr).
  • Scaling the words inside a chip makes them spill out of its background: scale the whole chip.
  • A CSS variable inside a gradient does not animate with a CSS transition without @property: GSAP writes it again every frame and the ring turns anyway.

Libraries

GSAP 3.15.0, Familjen Grotesk (font variabile) 5.3.0.

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