glyphline

Motion

How the word cursor and the sentence outline move, frame by frame.

Each highlight is a tween from what is on screen now to the new target. The interpolators are pure functions you can import and test (interpolateWord, interpolateSentence). Scrub through each kind of move:

The leading edge runs to the next word in the first half, the trailing edge catches up in the second. For a moment the cursor spans both words, like ink spreading. Dashed: start and end. Faint: frames at even steps of eased time.

Interruptions

A new target while a move is running starts a new tween from the current frame, not from the old target. Fast reading never queues moves up; the cursor bends toward the latest word.

Defaults

DurationEasing
Word cursor240 msease-out cubic
Sentence outline340 msease-out cubic
Selection120 msease-out cubic

At 240 words per minute a word lasts 250 ms, so the cursor lands before the voice moves on. The outline is slower because it travels further and should draw the eye less.

Reduced motion

With prefers-reduced-motion: reduce every highlight jumps. respectReducedMotion: false overrides it (for demos like this site's playground); animate: false turns motion off for everyone.

Without the highlighter

The geometry and motion are exported on their own, for a canvas renderer or another framework's tweens:

import { easeOutCubic, interpolateWord, wordPath } from "glyphline";

const tween = interpolateWord(current, { box: nextBox, o: 1 });
// each frame:
const f = tween(easeOutCubic(progress));
path.setAttribute("d", f ? wordPath(f.box) : "");

The library started this way: Folio fed the same interpolators to Svelte's Tween.

Made by Lucas Piera

On this page