Skip to content
animorio
IT
Back to the library

Paint chips

Scroll, TransitionsGSAP, CSS onlyAdvancedCompressed weight: Demo 7.3 KBGSAP + ScrollTrigger 45 KBFreeDownload the zip

Scroll inside the preview

A paint maker’s colour card: a row of tall, narrow chips slides sideways and the one that reaches the middle stretches to the top, then widens until it fills the screen, and its name writes itself large, from narrow to wide. Then it folds back into the row and the page keeps a pale wash of its colour. 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>Paint chips</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>
  <!-- the colour card of a made-up paint maker: a row of tall, narrow chips slides sideways as you scroll. The chip
       that reaches the middle stretches to the full height, then widens until it fills the screen, and its name writes
       itself in big letters, from narrow to wide. Then the name leaves, the chip folds back into the row and the page
       keeps a pale tint of it while the next chip slides in -->
  <main>
    <section class="apertura">
      <p class="piccolo">Fennick Paints</p>
      <h1 class="titolo">Six colours<br>for quiet rooms.</h1>
      <p class="piccolo piccolo--tenue">The autumn card. Scroll.</p>
    </section>

    <section class="racconto" data-racconto>
      <div class="palco" data-palco>
        <header class="testa" data-testa>
          <p class="marchio">Fennick</p>
          <p class="piccolo">Autumn colour card</p>
        </header>

        <div class="campioni" data-campioni>
          <div class="campione" data-campione style="--tinta: var(--clay)" data-nota="A warm earth, sun on brick">
            <span class="campione__nome">Clay</span>
          </div>
          <div class="campione" data-campione style="--tinta: var(--fog)" data-nota="A soft grey with a blue breath">
            <span class="campione__nome">Fog</span>
          </div>
          <div class="campione" data-campione style="--tinta: var(--saffron)" data-nota="A deep yellow, late afternoon">
            <span class="campione__nome">Saffron</span>
          </div>
          <div class="campione" data-campione style="--tinta: var(--moss)" data-nota="A green that sits back">
            <span class="campione__nome">Moss</span>
          </div>
          <div class="campione" data-campione style="--tinta: var(--lagoon)" data-nota="Still water, just before rain">
            <span class="campione__nome">Lagoon</span>
          </div>
          <div class="campione" data-campione style="--tinta: var(--plum)" data-nota="A dark red for the evening">
            <span class="campione__nome">Plum</span>
          </div>
        </div>
      </div>
    </section>

    <section class="apertura apertura--fine">
      <h2 class="titolo titolo--medio">Order a sample pot.</h2>
      <p class="piccolo piccolo--tenue">Every colour, in a small tin.</p>
    </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.

32 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 “Paint chips” from Animorio and fit it into my site

What it does

The autumn card of a made-up paint maker, Fennick, on a warm white with black ink and six paints. As the screen arrives, six tall, narrow chips rise one after the other from their foot, each with its name written small, reading upwards. Then the screen stops and, as you scroll, the row slides sideways: the chip that reaches the middle lifts a few pixels with a small snap, stretches to the top and bottom of the screen and then widens until it fills it, pushing its neighbours away. Its name writes itself large: the letters rise one after the other into their window and the word goes from narrow to wide with an elastic settle; below it a hairline draws itself, with a line about the colour on the left and its code on the right. The header changes colour too, but only where the paint covers it. Then the name leaves upwards, the hairline runs off to the right, the chip folds back into the row, first in width and then in height, with a small bounce, and the page stays washed with its colour while the next chip arrives. The last colour stays open. Everything follows the scroll, forwards and backwards.

How it works

Every chip is as big as the screen

Every chip is a layer in position absolute as big as the stage, filled with its paint and cut down by an inset() clip-path with rounded corners. The narrow chip and the one that fills the screen are the same element: only the cut changes. So the big name, the hairline and the copy of the header already sit in their place inside the chip and show only where the paint is.

Numbers instead of properties

The timeline, tied to the scroll with scrub SCRUB, does not move elements: it moves the position of the row and, for each chip, four numbers from 0 to 1 (rising into the row, lifting, stretching in height, widening). On every update of the timeline one function redraws all the cuts from those numbers: the widest chip decides where the others go, and they stay beside it with a gap that grows.

Height first, then width

Opening, the height goes from 0 to 1 with power3.inOut and the width starts a little later with expo.inOut: the chip becomes a column and then a wall. Closing does the opposite, and the height comes back with SETTLE, a back.out: the number dips a little under zero and the chip is shorter than the row for a moment before it settles.

The name from narrow to wide

Archivo is a variable font with a width axis (from 62 to 125). Every letter sits in an overflow hidden window and rises from below with yPercent; meanwhile a CSS variable --wd, which is the font-stretch of the word, goes from NARROW to WIDE with elastic.out. The size is measured beforehand at the final width, so the word always fits the screen.

The page keeps the tint

While the paint covers everything, the background of the stage changes to a mix of the page white and the paint (TINT): you do not see it change, but when the chip folds back the page is washed with its colour. The header is copied inside every chip in the colour that reads on that paint (black or white, chosen from the luminance): it shows only where the paint covers it.

Values to change

NameFileDefaultWhat it changes
STRIPscript.js56How wide a chip is in the row, in pixels (two thirds on a phone).
GAPscript.js12The space between two chips, in pixels.
NARROWscript.js62The width of the big letters as they arrive, from 62 (narrow) to 125 (wide).
WIDEscript.js112The width they settle on.
WEIGHTscript.js640The weight of the big name.
TINTscript.js0.16How much of the paint the page keeps once the chip folds back: 0 none, 0.5 a lot.
SETTLEscript.js'back.out(1.8)'The curve of the chip going back to its height: the number in brackets is how much it bounces.
SCRUBscript.js0.7How many seconds the drawing takes to catch up with the scroll.

Try them in the Playground

When to use it

To present a palette: the colour card of someone who sells paint, fabric or tiles, a season’s collection, the colours of a new brand on a launch page. It works with short names (one word) and five to eight colours; with more colours the section must be made longer.

On phones

The same, with narrower chips closer together, the row running off the right of the screen and the big name in proportion to the width.

With reduced motion

No movement: the row is already in place in the middle and each chip opens and closes with a cross-fade, its name already written; the wash on the page arrives with a fade too.

Pitfalls

  • Many fromTo tweens on the same object (the position of the row, the background of the stage) all render at once with immediateRender: the last one created wins, and the row opened the page already moved to the fifth chip, with the wrong background colour. From the second one on they need immediateRender: false.
  • With the name already written (in the version without movement) the big letters showed in pieces inside the narrow chips, because the cut shows everything underneath: the name and the hairline are hidden until the chip starts to widen.
  • With negative letter-spacing the tail of the y and the loop of the g stick out of their window: with overflow hidden they were cut straight. The windows have a padding that reaches past the letter and an equal negative margin, so the word keeps its size.
  • The page colour written in hexadecimal must be read as such: taken as a list of numbers it gave a random grey and the wash did not show.

Libraries

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

Compressed with gzip, the three demo files weigh 7.3 KB; the libraries: GSAP + ScrollTrigger 45 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