Repel Me Text

ProTypographypowered by @vectorvesper/motion

A headline whose letters flee the pointer in 3D — each glyph is its own spring, deflecting, tilting and lifting toward the camera as the cursor passes and settling back when it leaves. Three motion modes, four themes, and velocity casting that reads where the pointer is heading rather than where it is.

Repel Me Text

Included with membership

Members install Repel Me Text with one command and get the full source, the usage code and the Framer remix, licensed for client work. One membership covers the whole library and the CLI.

When to use it

A hero headline that is meant to be played with — a landing page, a studio title, a splash. It fills its container and expects to be the only thing in it, so give it a section rather than dropping it into a paragraph. It rewards a short word: every glyph is an independently simulated element.

  • Give the parent a real height. The component fills its container and has a 500px floor, but it is designed to own a viewport-sized section.
  • Keep the word short. Each character is measured and sprung on every frame, so a long string costs linearly.
  • Load Plus Jakarta Sans, or set fontFamily to a face you do load — the default stack names it first but does not bundle it.
  • Raise reach rather than strength if the effect feels too local; reach is the radius of influence, strength is only how far a letter travels.

Avoid:

  • Do not use it for text that has to stay readable while someone points at it. The letters move away from the cursor by design.
  • Do not set a light fontWeight. The deflection reads as mass moving, and thin letterforms have too little presence on screen for it to land.
  • Do not put two on the same screen. They both track the same pointer, so the whole page appears to flinch at once.
  • Do not wrap it in a container that clips overflow — letters lift toward the camera and travel outside their own box.

Props

A headline that gets out of the way. Each letter is its own spring: as the pointer approaches, glyphs deflect, tilt in three dimensions and lift toward the camera, then settle back once it passes. It reads the pointer's velocity and moves before the cursor arrives rather than after.

<RepelMeText />

The headline and its 3D stage. Paints its own background from the theme, so it is a section rather than an inline element.

PropTypeDefaultDescription
textstring"ANTICIPATION"The headline. Rendered uppercase; each character becomes its own sprung element.
mode"catenary" | "accordion" | "compass""catenary"How the letters respond. See the modes below — this is the prop that changes the character of the effect, the rest only tune it.
theme"obsidian" | "paper" | "slate" | "crimson""obsidian"Background and text colour together. Obsidian and slate are near-black, paper is off-white with dark type, crimson is near-black with a warm cast.
textColorstringfrom the themeOverrides the theme's text colour.
backgroundColorstringfrom the themeOverrides the theme's background. Set both this and textColor to ignore the theme entirely.
strengthnumber54Furthest a letter travels from its resting place, in pixels.
reachnumber280Radius of influence along the baseline, in pixels. This decides how many letters react at once — widen it before raising strength.
tiltAnglenumber42Largest 3D rotation a letter reaches, in degrees, across pitch, yaw and roll.
elevationZnumber72How far a letter lifts toward the camera, in pixels. This is what makes it read as depth rather than sliding.
scaleOnFocusnumber1.16How much a letter grows at the peak of its deflection.
perspectivenumber650Depth of the 3D scene, in pixels. Lower values exaggerate the perspective; higher ones flatten it toward an orthographic look.
dampnumber12How quickly a letter stops. Higher settles sooner; lower lets it overshoot and wobble.
tensionnumber0.09Spring stiffness — how hard a letter is pulled back to rest.
enableIntentbooleantrueCasts the pointer's velocity roughly a quarter-second ahead, so letters begin moving before the cursor reaches them. Turn it off for a strictly reactive feel.
fontFamilystring"'Plus Jakarta Sans', system-ui, -apple-system, sans-serif"Type stack for the headline. Plus Jakarta Sans is named first but is not bundled — load it yourself or the stack falls through to the system face.
fontSizestringa responsive clampA CSS class or size to replace the built-in responsive sizing, which runs from 13vw on small screens to 9.5rem on large ones.
fontWeightnumber | string800Weight of the headline. Keep it heavy — the effect depends on the letters having visual mass.
letterSpacingstring"-0.04em"Tracking. Tight by default so the letters read as one word before they separate.
onHoverGlyph(char: string, index: number) => void—Fires when the pointer comes within range of an individual character.
childrenReact.ReactNode—Rendered over the headline, for a subtitle or a call to action.
classNamestring""Applied to the wrapper.
styleReact.CSSProperties—Inline styles merged onto the wrapper.
mount"auto" | "eager""auto"When to start responding to the pointer. The default waits until the page has frame headroom to spare. Set "eager" when the heading is above the fold — the letters are readable either way, but they will not move until this is satisfied. Note this defaults the opposite way from the components that build a 3D scene: those start eagerly and take "auto" to defer. Both mean the same thing by "auto" — let the runtime pick the moment — the default just matches what each component already did. Neither setting takes it off the shared frame loop or overrides the reduced-motion preference.

Presets

PresetDescriptionKey Overrides
"catenary"The letters hang and swing like a slack line, dipping away from the pointer and stretching sideways. The default, and the calmest.—
"accordion"Letters compress and expand along the baseline, so the word breathes horizontally rather than deflecting.—
"compass"Every glyph turns to face the pointer wherever it is on the plane, rather than reacting only to horizontal distance. The most three-dimensional of the three.—
It reads the visitor's reduced-motion preference and holds every letter at rest — the headline still renders at full size in the chosen theme, it simply stops reacting to the pointer.
Each character is measured and integrated every frame, so cost scales with the length of the word rather than with the size of the type. It writes transforms straight to the DOM without re-rendering, so a short headline is cheap even though the simulation runs continuously.
Client component. It reads the pointer and measures its own glyphs, and waits until the main thread is quiet before it starts.
It draws on the shared frame loop rather than starting one of its own, so putting several animated components on a page costs one callback, not one each, and the scheduler can set decorative work aside when frames get tight. Letter positions are measured in a pass that runs before anything writes. Measuring them inline, immediately before writing a new transform to each letter, is the read-write cycle the browser cannot batch, and its cost grows with the length of the text.
Back to all components