Skip to content
animorio
IT
Back to the library

The line that bends into a chart

Scroll, SVGGSAP, CSS onlyMediumCompressed weight: Demo 6.8 KBGSAP + ScrollTrigger 45 KBFreeDownload the zip

Scroll inside the preview

A ceramics studio’s year of sales drawn by a single thin line: as you scroll, the flat line bends point by point into the chart of the twelve months, the month ticks drop out under it, the three figures that matter rise above their peaks and take their weight on a spring, and the last point lights up in blue. 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 line that bends into a chart</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the year of a made-up ceramics studio drawn by a single thin line. Scrolling down, the flat line bends point
       by point into the chart of the twelve months, the month ticks drop out from under it, the three figures that
       matter rise above their peaks gaining weight on a spring, and the last point lights up in the accent -->
  <main>
    <section class="apertura">
      <p class="piccolo">Kilnworth ceramics</p>
      <h1 class="titolo">A whole year<br>on one line.</h1>
      <p class="piccolo piccolo--tenue">Scroll down</p>
    </section>

    <section class="racconto" data-racconto>
      <div class="palco">
        <header class="testa">
          <p class="marchio">Kilnworth</p>
          <p class="piccolo piccolo--tenue">Pieces sold in 2025</p>
        </header>

        <div class="scena" data-scena>
          <svg class="tela" data-tela aria-hidden="true">
            <path class="tela__base" data-base />
            <g data-tacche></g>
            <path class="tela__riga" data-riga />
            <path class="tela__accento" data-ultima />
            <circle class="tela__punto" data-punto r="0" />
          </svg>

          <div class="mesi" data-mesi aria-hidden="true"></div>

          <figure class="cima" data-cima data-mese="4">
            <i class="cima__quota" aria-hidden="true"></i>
            <div class="cima__corpo">
              <figcaption class="cima__dida"><span data-dida>Spring fair</span></figcaption>
              <p class="cima__numero" data-numero></p>
            </div>
          </figure>
          <figure class="cima" data-cima data-mese="8">
            <i class="cima__quota" aria-hidden="true"></i>
            <div class="cima__corpo">
              <figcaption class="cima__dida"><span data-dida>New glaze</span></figcaption>
              <p class="cima__numero" data-numero></p>
            </div>
          </figure>
          <figure class="cima cima--ultima" data-cima data-mese="11">
            <i class="cima__quota" aria-hidden="true"></i>
            <div class="cima__corpo">
              <figcaption class="cima__dida"><span data-dida>Best month yet</span></figcaption>
              <p class="cima__numero" data-numero></p>
            </div>
          </figure>
        </div>
      </div>
    </section>

    <section class="apertura apertura--fine">
      <h2 class="titolo titolo--medio">Thank you for<br>a good year.</h2>
    </section>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.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 line that bends into a chart” from Animorio and fit it into my site

What it does

The numbers page of a made-up ceramics studio, Kilnworth, on a warm white with black ink and a single electric blue. The screen stops and a hairline draws itself from left to right. As you scroll, the line bends one point at a time, from January to December: each point rises to its height on a measured spring, goes a hair past it and settles, and where the line used to be a light trace stays behind, the baseline. As soon as a point leaves, its month tick drops out from under the line with a small bounce and the month name appears below. Above the three peaks that matter (the spring fair, the new glaze, the best month) a thin dimension line grows, the caption slides up and the figure comes in digit after digit, each from its own window, thin and narrow, then takes its weight and width on an elastic (Roboto Flex’s weight and width axes). At the end the last stretch, from November to December, is traced again in blue, the last point lights up and its figure turns blue. On a phone the months become initials and the figures near the edge move in to stay inside. Everything follows the scroll, forwards and backwards.

How it works

The twelve numbers

The sales of every month are a list, SALES, at the top of the script: the highest value sets the scale. Each month becomes a point with its x (the twelve points spaced evenly between the two margins) and a y going from the baseline up to the height of its value. The three figures above the peaks are in the HTML with data-mese, the month’s position from 0 to 11: the script writes the figure, taking it from the list.

Numbers instead of properties

The timeline, tied to the scroll with scrub SCRUB, moves numbers from 0 to 1: how much of the line is drawn, how far each point has risen, how far each tick has dropped, the final accent. On every update a single function redraws everything: the d attribute of the line’s path (a polyline cut where the pen has got to), the one of the light trace below, the ticks and the positions of the month names and figures.

The spring of each point

Each point’s tween is linear, and the BEND curve (back.out) is applied while drawing, with gsap.parseEase: so the point goes a hair past its height and comes back down the same way every time, both scrolling down and back up. Each point starts STAGGER after the one before, so the bend runs from January to December like a wave.

The ticks that drop

Each tick is a small vertical path that starts from the baseline and drops DROP pixels along bounce.out, a moment after its point has left the line; the month name below fades in moving down six pixels. On a phone the names become initials.

The figure that takes its weight

Each digit sits in a window with overflow: hidden and rises from below with a stagger. The whole figure has two CSS variables, --wg (font-weight) and --wd (the wdth axis in font-variation-settings): they start from LIGHT and 70 and reach HEAVY and 100 along the LAND curve, an elastic that takes them past and back. The colour of the last figure goes from black to blue with gsap.utils.interpolate together with the final point.

Values to change

NameFileDefaultWhat it changes
SALESscript.js[84, 102, 96, 148, 212, 176, 131, 158, 264, 221, 238, 341]The sales of every month, January to December: the highest sets the scale.
BENDscript.js'back.out(1)'The curve of each point rising: the number is how far it goes past before settling.
STAGGERscript.js0.45How long each point waits after the one before it starts.
DROPscript.js9How many pixels the month ticks drop under the line.
LIGHTscript.js200The weight of a figure while it rises.
HEAVYscript.js680The weight it lands on.
LANDscript.js'elastic.out(1, 0.5)'The spring of the figure taking its weight: a smaller second number means more shiver.
SCRUBscript.js0.8How many seconds the drawing takes to catch up with the scroll.

Try them in the Playground

When to use it

For a year’s numbers on an about page, in an annual report, on the page of an app or a shop that wants to show how it went: twelve values and two or three moments to tell. The values are changed in SALES and the figures above the peaks in the HTML (data-mese and the caption).

On phones

The same animations at adapted sizes: the chart takes the whole width with 26 pixel margins, the month names become initials, the figures are smaller and the ones near the edge move inwards so they never leave the screen (the dimension line stays on the point).

With reduced motion

No movement: the chart is already drawn, with its ticks and months. Scrolling, the three figures fade in one after the other, then the last stretch, the last point and its figure light up in blue.

Pitfalls

  • GSAP’s inline transform wipes out the class’s one: the figure block is centred on the point by the CSS (translateX(-50%) plus --sposta), so GSAP never touches it. Its parent carries it to the point, moved by hand by the script, and GSAP only moves the digits inside and the caption.
  • A one-pixel line on a whole coordinate falls across two rows of pixels and looks grey and blurred: the baseline sits on a half pixel (the rounded y plus 0.5), and the SVG viewBox is as big as the stage, one unit per pixel.
  • December’s figure, centred on its point, ran off the right of the screen (on a phone the caption too). Each figure is measured once on ScrollTrigger’s refresh, already at its final weight, and a CSS variable --sposta brings it back inside the margins; the dimension line stays on the point.
  • The weight of the figure changes its width as it arrives: measured at the light starting weight, it still ran off at the end. Before measuring, the script briefly sets --wg and --wd to their final values, then puts back the ones that were there.
  • The digits rise from windows with overflow: hidden and the spring takes them a little past: without a few hundredths of an em of room in the window (padding with an equal negative margin) the tops of the digits were cut during the bounce.

Libraries

GSAP 3.15.0, ScrollTrigger (GSAP) 3.15.0, Roboto Flex (font variabile, assi wght e wdth) 5.3.0.

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

Testing

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