009

Text Hover Distortion

£5

Characters react to cursor proximity with push, pull, wave, or rotation effects. The pointer field can be read from a whole section, buttons anywhere on the page can switch mode live, and a second channel can tint or blur the characters nearest the pointer.

advanced
4 more details
text-animationcursor-effectsmicro-interactionphysics
Text Hover Distortion - GSAP animation effect preview

This demo reads better at your own screen size than in the frame below:

About this effect

An interactive text effect where individual characters react to cursor proximity with physics-based displacement. Characters push away, pull toward, wave, or rotate based on their distance from the pointer, and the pointer field can be read from a containing section so the type starts reacting before the cursor is on top of it. Every setting can be retuned at runtime, so a single piece of type can demonstrate all four modes.

Read the full effect overview

The demo is a dark hero: one three-line statement in heavy Mona Sans filling the frame, the whole stage acting as the pointer field, and a segmented control switching the mode. The characters nearest the pointer also turn the accent colour and soften slightly, a second channel driven from the same distance, and the page opens with a pointer position already parked so the displacement is visible before anyone moves. Uses pure GSAP without any additional libraries.

What's included

10 items
  • Four distortion modes: push, pull, wave, and rotation
  • Per-character physics calculations based on cursor distance
  • Configurable influence radius, displacement strength and falloff curve
  • Pointer field readable from any container, not just the text itself
  • Optional colour, blur or weight changes that follow the same pointer response
  • Idle pointer position held until the real pointer arrives, so the effect shows in the first frame
  • Runtime retuning with setMode and setOptions, plus external mode and depth buttons
  • Live readouts of the current settings and a bubbling distort:change event
  • Smooth return-to-origin with three easing presets
  • Separate strength and radius for coarse pointers, with a tap-to-ripple touch fallback

Perfect for

6 use cases
  • Interactive hero headings on portfolio sites
  • Type specimen and foundry pages
  • Creative navigation menus and sidebar links
  • About page name and title displays
  • Interactive exhibit and gallery labels
  • Experimental typography showcases

How it works

2 sections

Characters respond as the pointer approaches: nearby letters move more, while those farther away remain quieter. Choose whether they push away, pull inward, form a wave or rotate toward the pointer. The active area can cover the text itself or a surrounding section.

Optional colour and blur deepen the response around the pointer, and characters settle smoothly back into place as it moves away. Controls can switch the mode and strength while the effect is running. Touch devices use a tap-triggered ripple.

Difficulty Advanced
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this effect's demo, 15 September 2026. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Paid effect

Purchase to unlock the code.

Buying Text Hover Distortion opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects.

£5 Standard license, unlimited projects

Browse free effects

Documentation

Quick Start

1. Add to your HTML <head>:

Code snippet omitted: it ships with the download.

2. Add before closing </body> tag:

Code snippet omitted: it ships with the download.

3. Add data attributes to any text element:

HTML: Code snippet omitted: it ships with the download.

Using It With Your Own Design

What the effect needs from your markup: one element per line of text, carrying data-text-distort. Its text content is read once and rebuilt as one span per character, so put nothing else inside it — no nested links, spans or icons. Give each line an id if you want to drive it from a button or show a readout of its settings.

The only CSS the effect depends on is in the "EFFECT REQUIREMENTS" block of style.css:

  • .distort-char { display: inline-block } — a character cannot take a transform otherwise. The script also sets this inline, so the rule is a belt-and-braces copy for when you restyle.
  • .sr-only — the effect hides the rebuilt characters from screen readers and leaves this readable copy behind. Delete the class and the text becomes unreadable to assistive tech.
  • Slack around the line. Characters move up to strength pixels out of their normal box, so a container that clips (overflow: hidden with a tight fit) will crop them mid-flight.
  • The mix channel is CSS, and optional. With data-distort-mix the effect writes --distort-mix (0 at rest, 1 under the pointer) onto every character and does nothing else with it. The demo's two .distort-char declarations (a color-mix() toward --distort-tint and a filter: blur() scaled by --distort-blur) are what turn it into colour and softness. Delete them and the channel is inert; repoint them at weight, opacity or a text-shadow and it becomes something else.

Everything else is the demo's own dressing and can be deleted: the stage, toolbar, prompt and segmented control, the statement's Mona Sans 800 sizing and its dark ground. The lines in the demo are white-space: nowrap purely so each stays on one line; the effect is happy with wrapped text. A multi-line statement is one data-text-distort element per line (the effect reads the element's text and rebuilds it, so a <br> inside one element is lost).

Options

Attribute Values Default Description
data-distort-mode push, pull, wave, rotate push Distortion behavior
data-distort-strength 1-100 30 Maximum displacement in pixels
data-distort-radius Pixels 150 Cursor influence radius
data-distort-ease smooth, elastic, snappy smooth Animation easing
data-distort-falloff linear, quadratic, exponential quadratic How effect fades with distance
data-distort-area CSS selector The text element Element whose pointer movement drives the effect
data-distort-scale Presence - Enable scale modifier
data-distort-opacity Presence - Enable opacity modifier
data-distort-mix Presence - Write --distort-mix (0 to 1) on each character for CSS to use
data-distort-idle "57% 46%", "0.57 0.46" - Pointer position held until the real pointer arrives
data-distort-mobile-strength 1-100 Same as strength Strength used on a coarse pointer
data-distort-mobile-radius Pixels Same as radius Radius used on a coarse pointer

Distortion Modes

push

Characters scatter away from the cursor. Great for repelling effects.

HTML: Code snippet omitted: it ships with the download.

pull

Characters are magnetically attracted toward the cursor.

HTML: Code snippet omitted: it ships with the download.

wave

Creates a radial wave pattern emanating from cursor position.

HTML: Code snippet omitted: it ships with the download.

rotate

Characters rotate to face the cursor direction.

HTML: Code snippet omitted: it ships with the download.

The Pointer Field

By default the text only reacts once the cursor is over it, which on a large headline means the effect starts abruptly. Point data-distort-area at a container and the field is read from there instead, so characters begin moving while the cursor is still approaching — and several lines can share one field and react together.

HTML: Code snippet omitted: it ships with the download.

Radius is still measured from each character, so give the display line a wider radius than the small print or the big type will feel unresponsive.

The Mix Channel

One input can have two visible consequences. Add data-distort-mix and every character carries a --distort-mix custom property that follows the same falloff as the displacement: 0 at rest, 1 with the pointer on the glyph. The effect never reads it back; what it does is up to your CSS. The demo tints toward the accent and blurs slightly:

CSS: Code snippet omitted: it ships with the download.

Without the attribute the property is never set, so the default behaviour is unchanged. filter on many characters costs raster time; keep the blur small and consider leaving it off for a long paragraph.

The Idle Pointer

By default nothing happens until a pointer enters the tracked area, so the first frame a visitor sees is the text at rest. data-distort-idle parks a synthetic pointer at a position inside the area (two fractions or percentages of its width and height) and renders one frame toward it, so the displacement is already visible on load. The first real pointer move takes over; leaving the area returns the text to rest as usual. The pose is re-taken after the webfont loads, on resize, and after a mode or option change.

HTML: Code snippet omitted: it ships with the download.

Coarse Pointers

A phone is a narrower field than a desktop stage, so a strength and radius tuned for one can throw the type off the other. data-distort-mobile-strength and data-distort-mobile-radius replace strength and radius when (pointer: coarse) matches; they also size the tap ripple. Leave them out and the desktop values are used everywhere.

External Controls

Buttons anywhere on the page can retune the text they point at. data-target takes an element id or any CSS selector; whatever it resolves to is reduced to the distorting text inside it, so a control can drive one line or a whole section.

HTML: Code snippet omitted: it ships with the download.

Buttons in a mode group share one data-target. The active button in the group gets an active class and aria-pressed="true"; style .active however you like.

Live Readouts

Any element with data-distort-value shows the current value of that option for the text its data-target resolves to, updated whenever a setting changes. Booleans read as on / off. Write the starting value into the markup so the readout is still correct with JavaScript disabled.

HTML: Code snippet omitted: it ships with the download.

Every change also fires a bubbling distort:change event on the text element, with the full option set in event.detail:

JavaScript: Code snippet omitted: it ships with the download.

Touch Support

On touch devices, tapping inside the tracked area triggers a wave animation outward from the touch point, sized by the mobile strength when one is given. The listener is passive and nothing is prevented, so the page still scrolls normally over the text. An idle pointer position still poses the text on load.

Accessibility

  • Respects prefers-reduced-motion — no animation for users who prefer reduced motion
  • Original text preserved for screen readers via aria-hidden wrapper
  • Keyboard users see static text (effect requires pointer input)
  • Mode buttons carry aria-pressed, kept in sync by the effect

Performance

  • Uses GSAP quickTo for smooth, optimized per-character animation
  • Bounds caching updated on scroll/resize and on entering the tracked area
  • RAF loop only runs while the pointer is inside the tracked area
  • will-change: transform applied to animated characters

Browser Support

Modern browsers (ES6+). Not compatible with IE11.

Dependencies

  • GSAP 3.12+

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.

Your cart

Your cart is empty

The Vault £99

The Vault library, plus future additions to the library.