Skip to content
animorio
IT
Back to the library

The cursors that run away

Hover, PhysicsGSAP, CSS onlyMediumCompressed weight: Demo 7.0 KBGSAP 28 KBFreeDownload the zip

The colleagues are cursors with a name: they drift around the board and move away when the pointer comes close; cornered or clicked, they stop and answer. Over the headline your cursor becomes a square that inverts the colours.

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 cursors that run away</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/wdth.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist-mono@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- a shared board: the studio's people are cursors with a name, and they keep away from yours -->
  <main class="board" data-board>
    <header class="top">
      <p class="brand">Offcut</p>
      <p class="top__line">The people at the studio</p>
    </header>

    <h1 class="headline" data-headline>Nobody here<br>likes to be<br>pointed at.</h1>

    <!-- the colleagues: the script writes one for each name in its list -->
    <div class="peers" data-peers aria-hidden="true"></div>

    <!-- your cursor: an arrow with its tag; over the headline it becomes a square that inverts what is under it -->
    <div class="lens" data-lens aria-hidden="true"></div>
    <div class="lens-frame" data-lens-frame aria-hidden="true"><i></i><i></i><i></i><i></i></div>
    <div class="you" data-you aria-hidden="true">
      <svg class="you__arrow" viewBox="0 0 24 26" width="24" height="26"><path d="M2 2 L2 21 L7.4 16.2 L11 24 L14.6 22.4 L11.2 14.8 L18.6 14.4 Z"/></svg>
      <span class="you__tag">You</span>
    </div>

    <p class="note" data-note>Go after them: they keep their distance. Corner one, or click it, and it answers.</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.

50 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 cursors that run away” from Animorio and fit it into my site

What it does

The board of an invented studio, with a huge headline in the middle: “Nobody here likes to be pointed at.”. Five coloured cursors drift around it, each with the name of someone at the studio, and yours is a dark arrow tagged “You”. Come closer and they move away, the more the closer you are, and when you leave they go back to their rounds. Against an edge they have nowhere to go: touch one, or click near it, and it stops, starts, and types an answer in its bubble. Over the headline your cursor opens into a square that inverts whatever is under it: the blue turns yellow and the white letters black. If nobody moves the pointer, a hand goes round by itself and every now and then catches one.

How it works

Everyone’s round

Each cursor has a spot, in fractions of the board, and drifts around it: a sine along a line of its own, with a period between 5 and 8 seconds, and a second, slower sine across it. No tweens: on every frame the wanted position is worked out from the time.

The push

If the pointer is closer than 260 px, a push is added to the wanted position along the line between them, outwards: 190 px when one is on top of the other, zero at 260. The distance is measured from where the cursor is now, so it keeps running while you chase it. The board’s edges stop the wanted position: that is where it gets cornered.

The spring

The cursor does not jump to the wanted position: a spring takes it there (stiffness 120, damping 15), integrated in steps of a hundred-and-twentieth of a second inside GSAP’s ticker. The arrow leans with its sideways speed. Near the right edge name and bubble move to the left of the arrow, with two different thresholds so they do not flicker on the line.

Caught

Under 26 px from the pointer, or with a click within 46 px, the cursor is caught: the wanted position becomes where it is, the arrow starts, and a timeline types the answer one letter every 0.05 seconds, holds it, rubs it out a little faster. Then it is free again, with almost a second in which it cannot be caught back.

The square that inverts

When the pointer enters the headline’s rectangle, a number goes from 0 to 1 in 0.4 seconds: it is the scale of a white square centred on the pointer, with mix-blend-mode: difference. White minus blue gives yellow, white minus white gives black. The four small squares at the corners live in a separate element, unblended, and the arrow fades while the square opens.

By itself

After three seconds without a pointer a hand sets off: it follows a Lissajous curve and the cursors avoid it as they would avoid you. Every six and a half seconds it heads straight for the nearest one, which that one time does not see it coming, and catches it. At the first real movement it disappears.

Values to change

NameFileDefaultWhat it changes
TEAMscript.js5Names, colours, spots and answers: one line per person.
REACH, PUSHscript.js260, 190From how far they start to move away, and how far they are pushed when the pointer is on them, in pixels.
SPRINGscript.js120 / 15The spring that carries them, stiffness and damping: less damping, more bounce.
DRIFTscript.js[90, 56]How far they drift from their spot: along their line, and across it.
CATCH, CLICKscript.js26, 46Under what distance a cursor is caught, and how far away a click still counts.
LETTERscript.js0.05The seconds per letter of the answer.
IDLE, HUNT_EVERYscript.js3, 6.5After how many seconds without a pointer the board plays by itself, and how often the hand catches one.
LENSscript.js[190, 0.26, 340]The inverting square: smallest side, share of the board’s width, largest side.

Try them in the Playground

When to use it

For the page of a team, a studio or a tool where many people work together: the opening of an about page, a hiring page, the launch of a collaborative product.

On phones

The cursors run from the finger while it is dragged, and a tap on one catches it. Reach, push and drift shrink with the board; near the edge names and bubbles open to the left. Once the finger is lifted, after three seconds the hand that plays by itself sets off again.

With reduced motion

The cursors stay still at their spots and do not run: bring the pointer onto one, or tap it, and its answer appears all at once for two seconds. The inverting square opens and closes without animation, and the board does not play by itself.

Pitfalls

  • mix-blend-mode blends with what lies under it in the same stacking context: if the square is the child of an element with a transform, that parent is a context of its own and the square stays white. Here it is a direct child of the board, and the transform is its own.
  • The push must be measured from where the cursor is now, not from its spot: measured from the spot, the field stays there and you reach the cursor without it moving.
  • Headline, notes and cursors have pointer-events: none: so the pointer always lands on the board and no pointerleave fires for every element it crosses.
  • With a finger pointerleave does not come: on a phone the end of a touch is read from pointerup and pointercancel.
  • A spring integrated once per frame blows up when the tab comes back after a pause: the frame time has to be capped (here at 0.05 s) and split into small steps.
  • A cursor that has just been freed has a moment in which it cannot be caught back: without it, with the pointer resting on top, it would answer for ever.

Libraries

GSAP 3.15.0, Anybody (font variabile) 5.3.0, Geist Mono (font variabile) 5.3.0.

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

Testing

Tested on 30 September 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 animations