
Marquee that speeds up with scroll
Scroll, Text, Hover
Free
A justified three-line headline, in the minimal style: every line arrives squeezed and hairline-thin and breathes out, wider and fuller, until it fills the column to the pixel; then the last word squeezes to make room for the next, and the two always share the whole column. Point at a line and it gets lighter without leaving the measure.
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 headline that fills the column</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>
<main class="stage" data-stage>
<!-- the column: two hairlines mark its edges; the script builds the headline inside, letter by letter, and
stretches every line on the width and weight axes until it fills the column exactly -->
<div class="measure" data-measure>
<i class="guide" data-guide aria-hidden="true"></i>
<i class="guide" data-guide aria-hidden="true"></i>
<h1 class="head" data-head></h1>
<p class="foot" data-foot>
<span class="foot__brand">Kerf Foundry</span>
<span class="foot__axes" aria-hidden="true"><span>wdth <b data-wd>100</b></span><span>wght <b data-wg>800</b></span></span>
</p>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>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.
22 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The headline that fills the column” from Animorio and fit it into my siteRoboto Flex has a width axis from 25 to 151 and a weight axis from 100 to 1000, but Fontsource's «wdth» file has the optical size axis fixed at 14, where the width barely changes (a narrow line is 80% as wide as a wide one). With the «standard» file, which keeps the opsz axis, and «opsz» 144 written in font-variation-settings, at width 25 and weight 100 the same line becomes a sliver: a fifth of its full width. Every letter is an inline-block span with its own values, written on each frame only when they change.
The column is 56% of the window wide (on a phone all of it, minus the margins). The type size is chosen by measuring every line at 100 px: big enough that every line, at the widest, reaches the column; small enough that each fits at the narrowest; as close as possible to the size that fills the column at a normal width. Then for every line and every word a binary search on the wdth axis (fifteen steps, measuring the real getBoundingClientRect) finds the width that makes it as long as the column. If the axis is not enough, letter spacing does the rest.
Every letter has two numbers from 0 to 1: b (the width, from SQUEEZE to the one that fills) and g (the weight, from 100 to WEIGHT). On the way in, the weight arrives first with power2.out and the width after it with a damped spring written as an easing function (BOUNCE sets the damping, and the spring ends exactly on 1), staggered from the middle outwards: so the line passes the column by a few pixels and comes back. On the way out the opposite, from the ends to the middle, with power3.in.
For every word of the last line a table of 41 widths is measured in advance, from the word squeezed and thin to the word full. During the change a number p goes from 0 to 1 with expo.inOut: the old word gets (1 − p) of the column, the new one p, minus a space between the two that opens and closes along a sine. From the table, by interpolation, comes how wide and how heavy each must be; when the space is less than the narrowest the word can be, scaleX squashes it the rest of the way. The sum is always the column.
For every line the width that fills the column is also searched at eleven weights between WEIGHT and the light weight (260, or 900 if WEIGHT is light): a number h from 0 to 1 picks the weight, and the right width is interpolated between the ones found. The pointer on a line takes h to 1 with a soft spring and back to 0 when it leaves; on a phone a finger held on the line does it. The same number, moved by the timeline with yoyo and staggered line by line, is the breath at the end of the round.
| Name | File | Default | What it changes |
|---|---|---|---|
LINES | script.js | ['Give it', 'room to'] | The first lines of the headline: each one widens until it fills the column. Lines of similar length breathe best. |
WORDS | script.js | ['breathe', 'stretch', 'wander', 'settle'] | The words of the last line, one at a time: each squeezes to make room for the next, and the last brings back the first. |
WEIGHT | script.js | 800 | The weight of the filled lines, from 100 (a hairline) to 1000 (black). |
SQUEEZE | script.js | 25 | The width the letters start from and go back to, on the wdth axis: 25 is the narrowest the typeface goes. |
BOUNCE | script.js | 0.4 | How far a line goes past the column before it settles: 0 stops dead, 1 bounces a lot. |
HOLD | script.js | 1.8 | How many seconds a word stays before the next one squeezes it out. |
SPEED | script.js | 1 | The speed of the whole animation: 2 is twice as fast, 0.5 half as fast. |
LOOP | script.js | true | Whether the headline breathes out at the end and starts again. With false it stays, after the final breath. |
For the opening headline of a site where typography is the star: a type foundry, a design studio, a magazine, a portfolio, the page of an event or of a product with a motto. It works with short sentences, a few words per line of similar length; the changing last line is good for saying several things in little space (services, adjectives, cities).
The same animation: the column is as wide as the screen minus the margins and the type is measured again to fill it. Keeping a finger on a line makes it lighter, as with the mouse; lifting it, the line fills up again.
Nothing widens or moves: the edge lines and the lines of the headline fade in already full, still from edge to edge; the change of word is a fade (the old one fades out, the new one appears in its place). No final breath and no breath under the pointer; at the end everything fades and starts again.
GSAP 3.15.0, Roboto Flex (font variabile, assi opsz, wght e wdth) 5.3.0.
Compressed with gzip, the three demo files weigh 8.3 KB; the libraries: GSAP 28 KB.
Tested on 14 October 2026
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.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.