Skip to content

shadcn.io is an independent project built on shadcn/ui

Text

Pro

Variable Proximity for Vue

Letters grow heavier as the pointer comes near, each by its own distance from it. For Vue with Ark UI, when a headline should answer the pointer.

UI library: Ark UI

Variable Proximity thickens each letter as the pointer comes near it: the letter right under the pointer is at its heaviest and the weight fades with distance, so a bold patch follows the pointer through the text. When the pointer leaves, every letter eases back to rest.

Use it for a large headline or a word on a landing page that invites the pointer over it. To light letters up rather than thicken them, use Spotlight Text; to swell a display word across its column, Text Pressure; to push letters apart, Kerning Text. The letters' centres are measured once as the pointer enters; each move writes the pointer's position to two CSS variables, and a CSS utility the install adds to your stylesheet works out each letter's weight from its distance, with no animation frame loop.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

<script setup lang="ts">
import { VariableProximity } from "@/components/ui/variable-proximity";
</script>
<template>
  <VariableProximity text="Bring the pointer closer" />
</template>

Demos

Falloff

falloff is how the weight fades between the pointer and radius: linear evenly, quadratic sharply, with only the nearest letters heavy, and smooth in a soft bell with a wide peak.

Preview width

Range

minWeight is the weight at rest and maxWeight the weight under the pointer, any weights your font has; radius is how far the pointer reaches, in pixels.

Preview width

Accessibility

Screen readers read the text once, from a visually hidden copy, never letter by letter. The effect only follows the pointer and changes no meaning, so keyboard and touch users miss nothing. Every letter keeps the width of its heaviest weight, so the text never reflows under the pointer; with reduced motion the weight follows the pointer without easing.

FAQ

Which font does it need?

A variable font with a weight axis, such as Inter, Geist, Hanken Grotesk or Roboto Flex, for the weight to change smoothly. With a static font the weights snap to the ones you've loaded, usually just regular and bold.

Can it change slant or another axis too?

Each letter's nearness, from 0 at the radius to 1 under the pointer, is the --variable-proximity-t variable on its .variable-proximity-glyph, so your stylesheet can drive any axis from it: .variable-proximity-glyph { font-variation-settings: "slnt" calc(-10 * var(--variable-proximity-t)); }. An axis that widens letters, such as wdth, will shift the line.

Why is the text a little wider than usual?

Each letter holds the width of its heaviest weight, so the line doesn't shift as letters thicken. A smaller maxWeight keeps it closer to its usual spacing.

Does it run on every frame?

No. It measures the letters once as the pointer comes over the text and then only writes the pointer's position on each move; the browser works out every letter's weight in CSS. Nothing runs while the pointer is elsewhere.

What happens on a touch screen?

A tap thickens the letters around it and they ease back when the finger lifts.

What happens with reduced motion?

The weight still follows the pointer, since it only answers what you do, but without easing between weights.

API Reference

VariableProximity

<span> data-slot="variable-proximity"

PropType
textstring

The text.

falloff?"linear" | "quadratic" | "smooth"

How the weight fades with distance: evenly, sharply near the pointer (quadratic), or in a soft bell with a wide peak (smooth).

Type
"linear" | "quadratic" | "smooth"
Default
"linear"
maxWeight?number

The weight right under the pointer. @default 900.

minWeight?number

The weight at rest, beyond the radius. @default 400.

radius?number

How far from the pointer letters are reached, in pixels. @default 120.

class?string

Merged with the part's classes.

CSS variableType
--variable-proximity-maxstring

The weight under the pointer (900).

--variable-proximity-minstring

The weight at rest (400).

--variable-proximity-radiusstring

How far letters are reached, in pixels, unitless (120).