Skip to content
animorio
IT
Back to the library

The typographic lens on the page

Text, HoverGSAP, CSS onlyMediumCompressed weight: Demo 7.2 KBGSAP 28 KBFreeDownload the zip

A minimal-style text animation: a book page set justified in a variable typeface, and the pointer is an invisible lens. Nearby letters gain weight, width and optical size with a soft falloff, the lines above and below step aside on a spring to make room, and the word under the centre lights up in vermilion. When nobody moves the pointer, an invisible reader reads the page line by line.

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 typographic lens on the page</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/full.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- a page of an invented book: the script splits the paragraph into lines and letters; an invisible lens follows the
       pointer (or reads the page by itself) and swells the letters it passes over on the weight, width and optical size
       axes, while the lines above and below step aside -->
  <main class="pagina" data-pagina>
    <header class="testa" data-entra>
      <span class="testa__libro">The Slow Reader</span>
      <span class="testa__capitolo">On margins</span>
    </header>
    <p class="per-chi-legge" data-leggibile></p>
    <div class="testo" data-testo></div>
    <footer class="folio" data-entra><span data-folio>112</span></footer>
  </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.

20 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 typographic lens on the page” from Animorio and fit it into my site

What it does

A page of an invented book, The Slow Reader, in the middle of a warm white: at the top the running head with the titles of the book and the chapter over a hairline, below a paragraph of seven justified lines in light Roboto Flex, at the bottom the page number. On opening the words rise line after line from the paper. Then, wherever the pointer passes, the letters swell: they gain weight, widen and go up in optical size, the more the closer they are to the centre, with a soft bell-shaped falloff that takes two or three words and a little of the lines above and below. The nearby lines step aside to make room, those above rise and those below drop, and they go back on a spring; within the line the words first use up the justification spaces, then the line grows around the lens without ever leaving the column. The word right under the centre turns vermilion. When the lens is moving it swells a little less; when it stops it comes into focus, swells a hair more and settles. If nobody moves the pointer, an invisible reader reads the page from left to right, line by line, returns to the start of the next one and at the end goes back to the top.

How it works

The lines as the browser set them

The paragraph is first set as ordinary invisible text at the right measure and size: the offsetTop of each word shows where the lines break. Then every line becomes a row of words with justify-content: space-between, that is a justified line, and every word is made of spans, one per letter. A line that would open its spaces too wide (more than half the type size between two words) stays ragged, as a compositor would do: on a phone it happens.

The lens

The resting position of every letter is read once, and again on resize. On every frame the distance from the centre of the lens gives a value between 0 and 1 along a bell curve (the exponential of the squared distance), and that value takes the weight axis from 360 to 820, the width axis from 100 to 126, the optical size to the type size plus 40 and a touch of grade: it is written in font-variation-settings, only for the letters that really change.

The lines that make room

Every line has its own bell in the vertical and asks for some extra room in proportion; the sum of that room moves the lines above up and the lines below down, keeping the line under the lens still. After writing the letters, the script reads in one go the scrollWidth of the lines it touched: whatever spills past the measure is taken back by moving the line left in proportion to where the lens is, so the line grows around the pointer. Two springs, vertical and horizontal, take the lines where they must go.

The focus and the reader

The lens follows the pointer on a spring. Its strength is another spring, lightly damped: while moving it aims at 0.8, standing still at 1, and getting there it overshoots a hair and comes back, which is the focus. When the real pointer is silent for 2.4 seconds, the target of the lens comes from a repeating GSAP timeline: a number from 0 to 1 that becomes the reading line by line, with the return to the next line and back to the top. With reduced motion nothing swells: only the word under the pointer changes colour.

Values to change

NameFileDefaultWhat it changes
RADIUSscript.js2The radius of the lens, in lines of text: the falloff is soft, bell-shaped.
REST_WEIGHTscript.js360The weight of the resting text, from 100 to 1000.
MAX_WEIGHTscript.js820The weight at the centre of the lens.
MAX_WIDTHscript.js126The width at the centre of the lens, on the wdth axis (100 is normal, up to 151).
LIFTscript.js40How far the optical size rises at the centre of the lens.
ROOMscript.js0.32How much the leading opens around the lens, in type sizes.
SPRINGscript.js[170, 15]The spring of the lines stepping aside: how stiff and how damped.
FOCUSscript.js[140, 9]The focus spring when the lens stops: the less damped, the more it settles.
SLACKscript.js0.55The widest space a justified line may open between two words, in type sizes; beyond it the line stays ragged.
LINE_TIMEscript.js2.6How many seconds the invisible reader takes per line.
TEXTscript.js'Read a page the way…'The text of the page.

Try them in the Playground

When to use it

For a reading page that wants to be noticed without making noise: a long read, a type foundry’s introduction, the opening of a magazine or a book, the about page of a graphic design studio.

On phones

The same animation: the dragged finger is the lens and, at rest, the invisible reader reads. The type size and measure fit the screen, and the lines that would open too much stay ragged.

With reduced motion

Nothing swells and nothing moves: the page fades in and only the word under the pointer changes colour.

Pitfalls

  • Widening letters would reflow the text on every frame: the lines are set once and become rows of words that never wrap; whatever spills over is taken back by moving the line.
  • Swelling the letters moves the layout: first all the changing letters are written and only then the widths of the touched lines are read, so the browser recalculates once per frame.
  • The writing tool turned the non-breaking space written as a backslash-u sequence into the real character: it is written with String.fromCharCode(160).
  • The IntersectionObserver started the loop before the page was set: the frame returns at once if there are no lines.
  • The words rise on opening with GSAP and the lens moves the lines: one element for GSAP and one for the spring, otherwise one transform wipes out the other.

Libraries

GSAP 3.15.0, Roboto Flex (font variabile, assi wght, wdth, opsz e GRAD) 5.3.0.

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

Testing

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