
Marquee that speeds up with scroll
Scroll, Text, Hover
Free
A short quote in the minimal style: two giant quote marks come in from opposite sides and close on the line like pincers, squeezing it on the width axis until it gets denser; then they let go, the line breathes out, wide and light, and the author's name runs underneath, riding the tip of a hairline.
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 quote marks that squeeze the line</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/standard.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/opsz.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage" data-stage>
<!-- what people read: the quote and its author; everything drawn below is only its picture -->
<p class="sr" data-read></p>
<!-- the script builds one line per quote in here, letter by letter -->
<div class="phrases" data-phrases aria-hidden="true"></div>
<!-- the two quote marks: they come in from the sides and close on the line like pincers -->
<span class="mark mark--open" data-mark aria-hidden="true">“<i></i></span>
<span class="mark mark--close" data-mark aria-hidden="true">”<i></i></span>
<!-- the author: a hairline draws under the quote and the name rides its tip -->
<div class="cite" data-cite aria-hidden="true">
<i class="cite__line" data-line></i>
<span class="cite__clip" data-clip><span class="cite__name" data-name></span></span>
<i class="cite__tick" data-tick></i>
</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.
17 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 quote marks that squeeze the line” from Animorio and fit it into my siteThe line is set in Roboto Flex with Fontsource's «standard» file, which keeps the optical size axis: with «opsz» 144 written in font-variation-settings the wdth axis goes from 25 (a sliver) to 151 (very wide), and the weight from 100 to 1000. The quote marks are in Fraunces, which has weight from 100 to 900: light when they arrive, full when they squeeze. Every letter of the line is an inline-block span, for the jolt and the entrance; width and weight are written once, on the whole line.
Everything depends on q: 0 is the line at rest (wdth 100, weight WEIGHT), 1 the squeezed line (wdth SQUEEZE, weight plus 80), −1 the line wide and light (wdth 151, weight 220). A function turns q into the two axes, and the timeline tweens move only q: it comes in at −0.35, reaches 1 with power3.out after the blow, goes back to −0.45 × BREATH with expo.out and settles on 0 with a damped spring written as an ease. The breath while it is read is a sine.inOut with yoyo; the pointer takes up to 0.28 off q.
On every frame the axes are written, then the getBoundingClientRect of the line is read just once: the inner edge of the ink of each mark stands at a distance g from the line, plus m times the way off the screen. Where the ink of “ and ” starts and ends is measured on a canvas with measureText (actualBoundingBoxLeft and Right) at nine weights, interpolated in between. So the pincers always touch the line, whatever its width at that moment.
The marks come in with power3.in, faster and faster, and the squeeze starts again from that speed. At the contact a number hit squashes them (scaleX 0.84 and scaleY 1.07 from the inner edge) and comes back with elastic.out; the letters give a 0.05 em jolt staggered from the ends towards the middle. While they squeeze, pr makes them tremble by a pixel along a fast sine. On the way out q goes back to 1 and a second number k crushes the line with scaleX down to zero while g goes to zero: the marks touch in the middle and fly away with power4.in.
The hairline under the quote is as long as the line at rest and draws with scaleX from the left (expo.out). The name sits in a window with overflow hidden as wide as the hairline, and its right edge is always on the tip: it comes out of the left end and rides the hairline until it stops at the end, aligned right. While it runs its wdth is 40 and it widens to 100 as it slows down; on the way out it does the opposite and slides past the end of the hairline.
| Name | File | Default | What it changes |
|---|---|---|---|
QUOTES | script.js | [['Words need air.', 'Mara Lindqvist'], ['Say less, slowly.', 'Teo Ballard']] | The quotes, one after the other: [the line, who said it]. Short lines, on one row: the longer it is, the smaller the type gets. |
WEIGHT | script.js | 560 | The weight of the line at rest, from 100 (a hairline) to 1000 (black). Squeezed it weighs 80 more. |
SQUEEZE | script.js | 25 | How tight the marks squeeze the line, on the wdth axis: 25 is the narrowest the typeface goes, 100 means they do not squeeze it. |
MARK | script.js | 2.4 | The size of the quote marks, in sizes of the line. |
BREATH | script.js | 0.7 | How far the line breathes out when the pincers open: 0 it just goes back, 1 it gets wide and light. |
HOLD | script.js | 2.4 | How many seconds the quote stays, breathing, before the marks close on it again. |
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 first quote comes back after the last one. With false the last one stays in place. |
For a quote or a review to put in the spotlight: a client's line on a studio's page, a restaurant's motto, a critic's line for a book or a show, a testimonial on a landing page. It works with short lines, read at a glance, and with a few quotes in a row.
The same animation: line, marks and gaps are measured again to fit the width of the screen, even when the line breathes out. Keeping a finger on the line makes it breathe as with the mouse; lifting it, it goes back to its place.
Nothing moves or squeezes: line, marks, hairline and name fade in already in place, stay, then fade out and the next quote appears. No breath under the pointer.
GSAP 3.15.0, Roboto Flex (font variabile, assi opsz, wght e wdth) 5.3.0, Fraunces (font variabile, assi opsz e wght) 5.3.0.
Compressed with gzip, the three demo files weigh 8.4 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.