Skip to content
animorio
IT
Back to the library

The colour columns

Three full-height columns, each the colour of a herb, with a brush mark that draws itself. Passing over one, the column widens and its drawn plant rises out of the colour.

Hover, SVGCSS only, GSAPMediumLifetime

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN.

The code for this animation is part of lifetime access.

The preview stays open: watch it, slow it down, try it on your phone.

Lifetime access

What it does

The screen is split into three columns of solid colour: sage, lavender and saffron. At the top of each a black calligraphic brush mark draws itself, one after the other, thickening where the stroke goes down and thinning where it runs sideways; below sit the name, a sentence with its fragrant word in italics, and a square button. Passing the mouse over a column, it widens, its mark lifts slightly, the other two lose a little colour, and its drawn plant rises from the bottom: the sage with its paired leaves and violet spike, the lavender with its stems, the saffron crocus with its red threads. Leaving it, the plant sinks back into the colour.

How it works

A nib in thirty lines

Each mark is a single SVG line. The script measures it with getPointAtLength at 120 points and, for each, moves one point left and one right along the normal: the thickness is width × (0.12 + 0.88 × sin(πt)^0.55) × (0.42 + 0.58 × |dy|), that is thin at the tips and full where the stroke goes down, like a nib held at an angle. The left points and the right ones, reversed, close the outline.

Drawing a filled shape

A filled outline cannot be drawn with stroke-dashoffset. The trick is a mask: the same centre line, 1.8 times as wide as the brush, with pathLength 1 and a dashoffset going from 1.02 to 0 in 1.3 seconds with power2.inOut. It uncovers the filled mark as it runs, and the leading edge is a clean cut, like the brush coming down.

The widening column

The columns are flex: 1 1 0, and the active one goes to flex-grow 1.5 with a 0.7-second CSS transition. The others get filter: saturate(0.72) brightness(0.95). The plant, under the text, starts at opacity 0, 5% lower and scale 1.06, and settles in 1.1 seconds: it seems to rise out of the colour and come to rest.

What is underneath

Instead of pointerenter on each column, a single pointermove listener on the window asks which column is under the pointer and lights only that one. With the keyboard, the column of the focused button lights up; on phones the columns stack, the plants stay visible and the marks draw themselves when each column reaches the screen.

Values to change

NameFileDefaultWhat it changes
SEGNIscript.js3 segniThe line of each mark, in 120 × 300, and the brush width: any line becomes a calligraphic stroke.
DISEGNAscript.js1.3The seconds to draw a mark.
--cstyle.css#A3B596, #A99BD1, #E6A23CThe colour of each column.
flex-growstyle.css1.5How much the active column widens.

When to use it

To present three lines, three seasons, three services or three characters of a product, when each has its own colour and one gesture is enough to meet them.

On phones

The columns stack, each almost a screen tall; the plants are always visible and each mark draws itself when its column enters the screen.

With reduced motion

The marks are already drawn, the columns keep their width and the plant appears in place with a 150-millisecond fade.

Pitfalls

  • To measure a path with getTotalLength and getPointAtLength, the path must sit in an SVG in the document: here an invisible SVG works as a ruler.
  • With pathLength 1 and stroke-dasharray «1 1» the dash repeats every 2: shifted by 1.02 to hide it, a sliver shows at the end of the line. With «1 3» the next dash is far away; the shift stays 1.02 rather than 1, because of rounding.
  • flex-grow animates well only if the columns start from flex-basis 0: with basis auto the width depends on the text and the transition jumps.
  • The filter on the dimmed columns belongs on the columns, not the container, or the active one dims too.

Libraries

GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.

Weight: 15 KB of our own files.

Testing

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