Join our Discord Community

React Variable Proximity Text

Interactive text with dynamic font variation based on cursor proximity. Perfect for React applications requiring engaging typography effects.

Powered by

Trying to implement interactive text effects?

Join our Discord community for help from other developers.


Most text effects are static and don't respond to user interaction—just fixed typography that sits there doing nothing. This component creates dynamic font variation based on cursor proximity, using variable fonts and real-time position tracking. As users move their cursor near letters, the font weight and optical size smoothly transition, creating an engaging magnetic effect.

Interactive font variation with cursor proximity

Text that responds dynamically to mouse movement with smooth font transitions:

Loading component...

Built with TypeScript and Motion for React applications, using variable fonts with custom font-variation-settings. The component tracks cursor position in real-time and applies different falloff algorithms (linear, exponential, gaussian) to create smooth proximity-based font transformations.

Installation

npx shadcn@latest add https://www.shadcn.io/registry/variable-proximity.json
npx shadcn@latest add https://www.shadcn.io/registry/variable-proximity.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/variable-proximity.json
bunx shadcn@latest add https://www.shadcn.io/registry/variable-proximity.json

Usage

import { useRef } from 'react';
import { VariableProximity } from "@/components/text/variable-proximity";

const containerRef = useRef(null);

<div ref={containerRef} style={{position: 'relative'}}>
  <VariableProximity
    label={'Hover me! Interactive text'}
    fromFontVariationSettings="'wght' 400, 'opsz' 9"
    toFontVariationSettings="'wght' 1000, 'opsz' 40"
    containerRef={containerRef}
    radius={100}
    falloff='linear'
  />
</div>

Why most text effects are boring

Most developers use static CSS hover effects—predictable transitions that only work when directly hovering elements. There's no sense of spatial awareness or magnetic attraction, just binary on/off states that feel mechanical and unengaging.

This React component uses requestAnimationFrame and real-time mouse position tracking to create proximity-based font variation. Variable fonts allow smooth interpolation between different font weights and optical sizes, creating the illusion that text has a magnetic field that affects nearby letters based on cursor distance.

The key insight: proximity creates natural interaction patterns. When font properties change based on distance rather than direct hover, it feels more organic and physically intuitive, like text responding to an invisible force field around the cursor.

Features

  • Real-time cursor proximity detection with configurable radius and falloff algorithms
  • Variable font support with customizable font-variation-settings for weight and optical size
  • Multiple falloff patterns: linear, exponential, and gaussian for different interaction feels
  • Performance optimized with requestAnimationFrame and position caching to prevent unnecessary calculations
  • Complete TypeScript support with proper prop validation and ref forwarding
  • Accessibility features with screen reader support and semantic markup
  • Free open source component compatible with Next.js and shadcn/ui design systems

API Reference

VariableProximity

Interactive text component with proximity-based font variation.

PropTypeDefaultDescription
labelstringrequiredText content to display with proximity effects
fromFontVariationSettingsstringrequiredBase font variation settings (e.g., "'wght' 400, 'opsz' 9")
toFontVariationSettingsstringrequiredTarget font variation settings for proximity effect
containerRefMutableRefObject<HTMLElement | null>requiredRef to container element for position calculation
radiusnumber50Proximity radius in pixels
falloff'linear' | 'exponential' | 'gaussian''linear'Algorithm for distance-based interpolation
classNamestring-Additional CSS classes
onClick() => void-Click handler function
styleCSSProperties-Inline styles

Font Variation Settings

Configure variable font properties for smooth transitions:

Setting TypeExample ValueEffect
Weight (wght)"'wght' 400" to "'wght' 900"Light to bold transitions
Optical Size (opsz)"'opsz' 12" to "'opsz' 72"Text size optimization
Width (wdth)"'wdth' 75" to "'wdth' 125"Condensed to expanded
Combined"'wght' 400, 'opsz' 12"Multiple properties

Falloff Algorithms

Different mathematical approaches for proximity interpolation:

AlgorithmBehaviorBest For
LinearStraight line interpolationConsistent, predictable effects
ExponentialAccelerating curveSharp, dramatic transitions
GaussianBell curve distributionNatural, organic feeling

Common gotchas

Font variation doesn't work: Ensure you're using a variable font that supports the font-variation-settings you've specified. Test with Google Fonts like "Roboto Flex" or "Inter Variable" which have extensive variation axis support.

Performance issues: The component uses requestAnimationFrame for smooth updates. On slower devices, consider increasing the radius or using fewer letters. The component includes position caching to minimize unnecessary calculations.

Container ref is null: The containerRef must point to a mounted DOM element. Ensure the ref is attached to a parent container and the component is rendered after the container mounts.

Letters not responding to cursor: Check that the container has position: relative and the containerRef is properly passed. The component calculates relative positions within the container bounds.

Accessibility concerns: The component includes screen reader support with sr-only content. However, rapidly changing font weights might be distracting for some users. Consider respecting prefers-reduced-motion settings.

Integration with other components

Perfect for hero sections in Card layouts or interactive headings in Dialog modals. Works excellently with Button components for dynamic call-to-action styling that responds to nearby cursor movement.

For creative interfaces, combine with Avatar components for profile name effects or Badge components for status indicators that react to proximity. The component integrates seamlessly with Tabs for section headers and works well within Sheet overlays for interactive navigation elements.

Questions developers actually ask