Skip to content
animorio
IT
Back to the library

The road that runs as you scroll

3D, ScrollGSAP, CanvasMediumCompressed weight: Demo 7.6 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

Scroll inside the preview

A minimal-style scroll animation: a road seen from the driver’s seat, made only of lines, running towards you as fast as you scroll, with bends coming in from the horizon. At the bottom the speed, written large, widens and gains weight as you speed up; at the end the road brakes and a sign drawn in a single line says where you have arrived.

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 road that runs as you scroll</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- a made-up guide to slow roads, Verge. The stage sticks while you scroll: a road seen from the driver's seat, made
       only of lines, runs towards you as fast as you scroll; the speed is written at the bottom and grows wider and
       bolder as you speed up. At the end of the section you arrive, and a sign drawn in one line says where. -->
  <main>
    <section class="corsa" data-corsa>
      <div class="palco" data-palco>
        <canvas class="strada" data-strada aria-hidden="true"></canvas>

        <header class="testa">
          <p class="marchio" data-entra>Verge</p>
          <p class="testa__nota" data-entra>Slow roads, one at a time</p>
        </header>

        <div class="cartello" data-cartello aria-hidden="true">
          <svg class="cartello__segno" viewBox="0 0 120 150" preserveAspectRatio="xMidYMax meet">
            <path data-cartello-filo d="M60 150V62H8V8h104v54H60"/>
          </svg>
          <p class="cartello__nome" data-cartello-nome>Lower Harlow</p>
        </div>
        <p class="arrivo" data-arrivo>You have arrived.</p>

        <div class="tachimetro" data-tachimetro>
          <p class="tachimetro__numero"><span data-numero>0</span><span class="tachimetro__unita">km/h</span></p>
          <span class="tachimetro__riga" aria-hidden="true"><span class="tachimetro__pieno" data-pieno></span></span>
        </div>

        <p class="cenno" data-entra><span class="cenno__dentro" data-cenno><span>Scroll to drive</span><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v13M4.5 10.5 10 16l5.5-5.5"/></svg></span></p>
      </div>
    </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="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.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.

21 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 road that runs as you scroll” from Animorio and fit it into my site

What it does

A warm white page with the name of a guide to slow roads, Verge, at the top. On opening a road stretches out from the bottom of the screen to the horizon: two thin edges narrowing in perspective, the dashed centre line, small posts at the sides and the pale line of the horizon; at the bottom left a large ‘0 km/h’, narrow and light, with a thin line under it. As you scroll the page stays still and you drive: the dashes of the centre line and the posts run towards you, faster the faster you scroll, and the speed below rises and falls with the scroll, a whole number that widens and gains weight as you speed up and narrows again as you slow down, while the line under it fills. The bends, always the same and in the same places, come in from the horizon and bend the edges right and left, then pass under you. At top speed the centre line turns red. Towards the end of the section the road brakes by itself until it stops, even if you keep scrolling; the view gives a small nod forwards and back, on the right a sign with the name of the place, Lower Harlow, draws itself in a single line, and ‘You have arrived.’ appears at the top. Scrolling back up takes you back along the same road.

How it works

A road in true perspective

The road is a canvas redrawn on every frame. In front of the camera there are 160 depth steps, longer with distance (z grows geometrically), and for each one the script knows how far the middle of the road is shifted sideways. A point of the world (x, height, z) goes on screen by dividing by z: the screen x is half the width plus f times x over z, the y is the horizon plus f times the camera height minus the point’s, over z. The camera is placed so that the carriageway, at the bottom edge of the screen, is as wide as the screen.

Bends that add up

The bends are a fixed list: where they start on the road, how long they are and how much they turn. At every step the curvature of the stretch of road being looked at is added to the heading, and the heading to the sideways shift, like a car following the road: so a far bend bends the edges near the horizon and, as you scroll, comes closer until it passes under you. Every bend starts and ends gently (sine squared), so the edges never make a corner.

The road tied to the scroll

A ScrollTrigger on the section gives the scroll point from 0 to 1, and a function turns it into metres of road: still for the first four hundredths, then at a steady pace, and in the last stretch a parabola that brakes down to zero with the same slope where the two parts meet. The dashes of the centre line and the posts sit at fixed points of the road, every 12 and every 40 metres: it is the position that changes, so they run towards you by themselves, faster the faster you scroll, and every ride is the same.

The speedometer

The speed is real: the metres travelled in a frame divided by the frame’s time, against a reference speed (100 km/h means the whole road in CRUISE seconds). An exponential average smooths it over SMOOTH seconds, so the number rises and falls without shaking. The whole number only changes when it really changes; the typeface’s axes follow the speed, wdth from 62 to 125 and wght from 300 to 820, and the line underneath fills with scaleX.

The arrival and reduced motion

After the braking, a timeline tied to the scroll draws the sign with stroke-dashoffset on a single-line path (post and board), brings the name up from wide and light to narrow and full and lights up the arrival line. On arrival the view nods: the horizon drops a few pixels and comes back with elastic.out. With reduced motion there is no Lenis and the road stays still; the number still tells the scroll’s speed, without changing shape, and the sign fades in.

Values to change

NameFileDefaultWhat it changes
PLACEscript.js'Lower Harlow'The name of the place you arrive at, written on the sign at the end.
MAX_KMHscript.js130The speed that fills the speedometer’s line, gives the number its full width and weight and lights up the centre line.
CRUISEscript.js8How many seconds the whole road takes at 100 km/h: the higher, the faster the speedometer reads for the same scroll.
DASH_EVERYscript.js12Every how many metres a dash of the centre line starts.
LANE_DASHscript.js0.45How long a dash of the centre line is, as a share of that distance.
CURVESscript.js1How tight the bends are: 0 is a straight road, 2 twice as tight.
POSTSscript.jstrueThe posts at the sides of the road.
LINEscript.js1.5The thickness of the edges and the posts, in pixels.
SMOOTHscript.js0.35How many seconds the speedometer takes to follow the real speed: the higher, the calmer.
RIDEscript.js1How much scroll the ride takes: 2 means twice as much.

Try them in the Playground

When to use it

For the page of a trip, a car rental, a driving school, a car brand or a road guide: a scroll story that makes you feel the road and the speed without drawing a car.

On phones

The same animation with adapted sizes: the carriageway is a little wider than the screen, the horizon a little lower, the number smaller; you drive with your finger as with the mouse.

With reduced motion

No smoothed scrolling and no running: the road stays still with its far bends, the number tells the scroll’s speed without changing shape and at the end the sign fades in.

Pitfalls

  • With equal depth steps the road near the horizon was made of few points and the far bends had corners; with steps in geometric progression the points gather where they are needed.
  • The speed worked out from one frame to the next shook (Lenis hands over the scroll in small steps): an exponential average over SMOOTH seconds calms it without making it lag.

Libraries

GSAP 3.15.0, ScrollTrigger 3.15.0, Lenis 1.3.26, Archivo (font variabile) 5.3.0.

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

Testing

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