Skip to content
animorio
IT
Back to the library

The counting circle

SVG, TextGSAPAdvancedCompressed weight: Demo 6.8 KBGSAP 28 KBFreeDownload the zip

A product launch countdown drawn with a single line: a thin circle draws itself, opens into six arcs that become the number, and every new figure is redrawn from the strokes of the one before. At zero the arcs turn back into the circle. Minimal style.

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 counting circle</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/jost@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <!-- one thin line: a circle that draws itself, breaks into arcs and counts down a product launch, each figure
         redrawn from the arcs of the one before; at zero the arcs close back into the circle -->
    <svg class="figure" viewBox="-90 -62 180 124" role="img" aria-label="Countdown" data-figure>
      <g class="line" data-line></g>
    </svg>
    <p class="caption">
      <span class="caption__clip"><span class="caption__name" data-name>Halo</span></span>
      <span class="caption__clip caption__state" data-state>
        <span class="caption__phrase caption__phrase--soon" data-soon>launches in</span>
        <span class="caption__phrase caption__phrase--live" data-live>is live</span>
      </span>
    </p>
  </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.

15 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 counting circle” from Animorio and fit it into my site

What it does

On a warm white page a thin black line draws a circle starting from the top, while the circle turns a little and settles; underneath, the letters of “Halo launches in” rise out of a slot one by one. The circle opens into six arcs with a small snap, then the arcs fly to their places and become a 10: the stem and the beak of the one, the two curves and two sides of the zero. Every second the number changes, and the new figure does not appear out of nothing: each stroke goes to the nearest stroke of the new figure, its head first and its tail after, like a pen going over it again, and lands with a hair of bounce. From 10 to 9 the two figures melt into one. From 3 the line turns orange. At zero the zero opens back into arcs, the arcs close into the circle, which gives a small elastic kick; “launches in” drops away, “is live” rises in its place in orange and the name gets heavier, one letter after the other. After a few seconds the circle unwinds and wipes itself out as it turns, the words leave, and it all starts again. A click or a tap starts it over.

How it works

Figures made of arcs

Every figure is drawn by hand from straight lines and circle arcs in a box 100 tall: the zero is a stadium (two half circles and two sides), the eight two circles, the six a diagonal running into a circle, the nine is the six upside down. Every figure has exactly three strokes; the ones with fewer (the one, the seven) repeat a piece of a stroke on top of it, where it does not show. Each stroke is sampled into 72 points spaced evenly along its length, so any two strokes have the same points and can be blended.

Six strokes for everything

The line on the page is six paths, always the same ones. The circle is six arcs of 60 degrees; a two-figure number uses three strokes per figure; a single figure takes them twice, one on top of the other. The figures are set side by side by their true width (the width of their points, not of the box), so the one is narrow and the 10 sits in the middle as it would in a good typeface.

The nearest stroke

At every change the script tries every way of giving the six strokes on the page to the six strokes of the new figure (720) and, for each pair, the stroke turned the other way round as well: it picks the way that moves the line the least, adding up the distances of the points. That is why the 9 grows out of the 10 keeping the ring of the zero, and the 8 out of the 9 keeping its loop: the figure is redrawn from the one that was there.

Head and tail

The movement is one tween on a clock, and every point has its own time: the point at the end of the stroke starts later, by a share TRAIL, and every stroke starts 35 thousandths after the one before. Each point's value goes through the EASE (back.out), so the settling runs along the line like a wave. Meanwhile the tail of the stroke lifts off the page, the more the further it goes, and comes down as it lands: you see the head running and the stroke redrawn behind it. Drawing and wiping are stroke-dasharray, worked out on the true length of each stroke.

Direction

A paused timeline only holds the moments (drawing, opening, every second, closing, leaving) with tl.call, and every moment starts its tweens from the state it finds the line in: so the next round starts clean with restart. The line of type below is split into letters that rise and drop out of a window with hidden overflow; the window's width follows the new phrase, and the name gets heavier letter by letter on the wght axis of the variable font.

Values to change

NameFileDefaultWhat it changes
STARTscript.js10The number the countdown starts from, 1 to 99.
TICKscript.js1How many seconds each number stays: 1 is a real countdown.
MORPHscript.js0.56How many seconds a stroke takes to redraw itself into the next figure (it always stays shorter than the tick).
TRAILscript.js0.42How far the tail of each stroke lags behind its head: 0 moves the whole stroke at once, 0.8 makes it run like a pen.
EASEscript.js'back.out(1.7)'How the strokes land: back.out goes a hair past the spot and settles; elastic.out(1, 0.5) bounces more, power3.out stops dead.
STROKEscript.js1.5How thick the line is, in hundredths of the figure's height.
ACCENT_FROMscript.js3From this number down the line turns the accent colour.
HOLDscript.js2.4How many seconds the closed circle stays once the product is live, before it unwinds and starts again.

Try them in the Playground

When to use it

For the wait before a launch: a product's coming soon page, the countdown before a live stream, the opening of a sale, the start of an event, the screen before a video. Also as an elegant loading screen for a brand that lives on thin lines and empty space.

On phones

The same animation with the sizes adapted: the circle and the number take almost the whole width, the line stays thin in proportion, the type underneath gets smaller. A tap starts it over.

With reduced motion

Nothing moves: the circle fades in already drawn, each number fades into the next, at zero it fades into the orange circle and the words change with a fade.

Pitfalls

  • Halfway, strokes travelling far crossed each other and the figure turned into a tangle for a moment: now the tail of a stroke lifts off the page while it travels (up to 72% of the stroke, in proportion to how far it goes) and comes back down as it lands, like a pen redrawing. Strokes that hardly move do not lift.
  • With round caps a stroke of zero length still draws a dot: at the start of the drawing and at the end of the wipe six dots would be left on the circle. Below a minimum length the stroke is hidden with visibility.
  • Blending points with the same index, a stroke that runs the other way in the new figure turns over on itself and makes a knot halfway: for every pair the reversed stroke is tried as well and the nearer one kept.
  • After picking the nearest strokes, the arcs of the final circle are no longer in order round the ring, and the wipe (one arc after another) would go in jumps: before it unwinds the line is put back in the right order, which with the circle closed is the same picture.
  • The moves start from the state they find the line in, so they cannot sit nested in a repeating timeline (going back to the start would run them backwards): the timeline only holds tl.call, every moment builds its own tweens and at the end there is a reset and restart. The first moment sits at 0.02 seconds, because restart does not call a function placed exactly at zero.

Libraries

GSAP 3.15.0, Jost (font variabile) 5.3.0.

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

Testing

Tested on 14 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 animations