Text Cursor Proximity
A text component that animates the letters based on the cursor proximity
Installation
1pnpm dlx shadcn add @fancy/text-cursor-proximity
Understanding the component
The TextCursorProximity
splits its text into letters that respond to cursor movement by adjusting their CSS properties based on the distance between the letter and cursor position.
- Splitting text into individual letters
- Tracking cursor position relative to each letter
- Smoothly transitioning CSS values with motion's
useTransform
hook - Supporting multiple falloff patterns for the effect
How it works
The component calculates the distance between the cursor and each letter in real-time. When the cursor comes within the specified radius
of a letter, that letter's CSS properties (like scale, color, etc.) smoothly interpolate between two states. For this, we use the motion
library's useTransform
hook, which maps the CSS properties from the styles.*.from
state to the styles.*.to
state based on the proximity value (which ranges from 0 to 1).
- Default state: (defined in
styles.*.from
) - Target state (defined in
styles.*.to
)
You can interpolate any value that motion supports (which is actually any CSS value, even those that can't be animated by the browser, like mask-image
).
The closer the cursor gets to a letter, the closer that letter moves toward its target state.
Examples
Falloff
With the falloff
prop, you can control the type of falloff. It can be either linear
, exponential
, or gaussian
. The following demo showcases the exponential
one. The effects are best observed on a larger block of text.
Notes
It seems like interpolating on large number of letters simultaneously can be a bit slow, even when we're avoiding re-renders with state updates. If you're experiencing performance issues, try to limit the length of the text you're animating.
Credits
Ported to Framer by Framer University
Props
Prop | Type | Default | Description |
---|---|---|---|
children* | React.ReactNode | - | The content to be displayed and animated |
as | ElementType | "span" | The HTML element to render the component as |
styles* | Partial<{ [K in keyof CSSProperties]: { from: string | number, to: string | number } }> | - | CSS properties to animate and their from/to values |
containerRef* | React.RefObject<HTMLDivElement> | - | Reference to the container for mouse tracking |
radius | number | 50 | The radius of the proximity effect in pixels |
falloff | "linear" | "exponential" | "gaussian" | "linear" | The falloff pattern for the proximity effect |
className | string | - | Additional CSS classes for styling |