webdevpuneet.com

Proximity Glow Button — Cursor Distance Hover Effect

Proximity Glow Button · Buttons · Plain HTML, CSS & JS · Live preview

CategoryButtons

Copy & paste

Source Code

<div class="pg-stage">
  <p class="pg-hint">Move your cursor around the page — the buttons glow brighter the closer you get, even before touching them</p>
  <div class="pg-row">
    <button class="pg-btn" data-radius="260"><span>Deploy now</span></button>
    <button class="pg-btn" data-radius="180"><span>View docs</span></button>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Document-wide mousemove listener — glow reacts to cursor position anywhere on the page, not just on :hover
Continuous 0-1 glow intensity via CSS custom property, not a binary hover class toggle
Squared distance falloff for a perceptually natural "brightness" curve
Per-button data-radius attribute controls each button's independent sensing distance
A single --pg-glow custom property drives box-shadow, border color-mix, and halo opacity together
CSS color-mix() blends the border color toward the glow tint proportional to intensity
Blurred: :before pseudo-element halo layered beneath the label for a soft ambient light look
mouseleave on document resets all buttons cleanly when the cursor exits the viewport
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons
Live split-pane editor — preview updates as you type

About this UI Snippet

Proximity Glow Button — Continuous Cursor-Distance Glow Before the Cursor Even Touches It

Screenshot of the Proximity Glow Button snippet rendered live

Most button glow effects are binary: nothing happens until the cursor crosses the button's edge, at which point CSS :hover flips a fixed style on. This effect is continuous instead — the glow intensity is a real number between 0 and 1 that increases smoothly as the cursor approaches from anywhere on the page, so the button visibly "senses" an approaching cursor well before contact, similar in spirit to a magnetic button's pull but applied to light intensity instead of position.

A document-wide listener, not a button-scoped one

The trigger mechanism itself is what makes this different from a hover effect: a single mousemove listener on document fires on every cursor movement anywhere on the page, and for every button on the page it recomputes a distance-based intensity — not just for the button the cursor happens to be over. This lets multiple buttons glow in relation to the same cursor position simultaneously, each with its own falloff radius.

The distance-to-intensity formula

For each button, getBoundingClientRect() gives its center point. The straight-line distance from the cursor to that center is compared against a per-button data-radius attribute (in pixels) — the maximum distance at which any glow is visible at all. The raw ratio t = 1 - dist / radius is clamped to [0, 1], then squared (t = t * t). Squaring is the key perceptual tweak: without it, a cursor that's still fairly far away would already produce a noticeably bright glow; squaring keeps the glow nearly invisible until the cursor is meaningfully close, then it ramps up quickly in the final approach — closer to how a real light source's perceived brightness falls off with distance.

Writing intensity as a CSS custom property

Rather than toggling classes, the JS writes the computed t directly to a CSS custom property, --pg-glow, via style.setProperty. Every visual consequence of proximity — the ambient box-shadow, the border color mixed toward indigo via color-mix(), and the blurred ::before halo's opacity — all reference var(--pg-glow) directly in CSS, so a single JS-written number drives three coordinated visual changes without any additional JS branching.

Per-button radius via data-radius

Each button carries its own data-radius attribute, so different buttons can have different "sensing" distances — a primary CTA might use a larger radius (260px) to feel more magnetic and attention-grabbing than a secondary button (180px).

Resetting when the cursor leaves the page

A mouseleave listener on document (fired when the cursor exits the browser viewport entirely) resets every button's --pg-glow back to 0, since without an active cursor position there's nothing to measure distance against.

Step by step

How to Use

  1. 1
    Move the cursor around the pageWithout touching either button, move your cursor closer and farther away — notice the glow ramps up smoothly well before you reach the button.
  2. 2
    Compare the two buttonsThe first button has a larger data-radius (260) and starts glowing from farther away than the second (180).
  3. 3
    Adjust the sensing radiusIn the HTML panel, change each button's data-radius attribute to control how far away the glow starts appearing.
  4. 4
    Change the glow colorUpdate the rgba(99,102,241, ...) values in the box-shadow rule and the color-mix() target color in the CSS panel.
  5. 5
    Adjust the falloff curveIn the JS panel, change the t = t * t line — remove it for a linear falloff, or raise the power (t*t*t) for glow that appears even more suddenly at close range.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

BTN
Primary CTA buttons on dark landing pages
A CTA that glows as the cursor approaches draws the eye toward it before the user even consciously decides to click, more effectively than a static hover state.
Product launch and futuristic dashboard UIs
Pairs naturally with a dark, glassy interface aesthetic — the proximity reaction reads as ambient, responsive lighting rather than a simple color swap.
Learn continuous vs. binary interaction states
A clear example of replacing a boolean :hover trigger with a continuous, distance-driven value — a pattern used across cursor-reactive effects like the neon glow.
Gaming and creative-tech portfolio sites
Use on a hero CTA for a portfolio or product that wants to feel technically impressive — the glow-before-touch reaction is a small but memorable detail.
Onboarding "next step" emphasis
Use a larger sensing radius on the button representing the intended next action to subtly guide user attention as they move the cursor around the screen.
Related: Magnetic Button
Combine with the Magnetic Button for a CTA that both glows from a distance and physically pulls toward the cursor once it gets close.

Got questions?

Frequently Asked Questions

A :hover glow is binary — off until the cursor crosses the button's exact boundary, then fully on. This effect computes a continuous distance value on every mousemove anywhere on the page, so the glow visibly ramps up as the cursor approaches from far away, well before it touches the button.

A raw linear ratio makes the glow noticeably visible even when the cursor is still fairly far from the button. Squaring keeps the glow nearly imperceptible at greater distances and lets it build up quickly only in the final approach, which reads as a more natural, light-source-like falloff.

It is the maximum distance in pixels, measured from the button's center to the cursor, at which any glow starts to appear at all. A button with a 260px radius starts glowing from farther away than one with a 180px radius.

Writing one number to --pg-glow lets CSS itself compute three coordinated effects (box-shadow spread and opacity, color-mix on the border, and a blurred halo's opacity) directly from that single value using CSS functions like calc() and color-mix() — simpler and faster than computing and writing three separate style properties from JavaScript every mousemove.

Each mousemove event does a getBoundingClientRect() and a distance calculation per button, which is cheap for a handful of buttons. For dozens of proximity-reactive elements on one page, consider throttling the mousemove handler or caching bounding rects and only recomputing them on scroll/resize.

Yes. Click "JSX" for a React component. Attach a single document mousemove listener in a useEffect with an empty dependency array, keep refs to each button, and write --pg-glow directly via ref.current.style.setProperty inside the handler to avoid state-driven re-renders on every mouse movement.