Magnetic Button
A magnetic button that is pulled towards the cursor as it approaches, with a parallax on the inner text and a spring back once the cursor leaves.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add magnetic-button.enMagnetic Button is a React magnetic button component built with Tailwind CSS and Motion. As the mouse moves over it, the button shifts toward the cursor based on its distance from the center, the inner label moves half as far in the opposite direction, and a spring brings it back when the cursor leaves.
Playground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<MagneticButton/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
When to use
- The main call to action on a portfolio or creative studio site, such as "Contact us" or "View work".
- The single CTA in a landing page hero, where the button should respond visibly to the cursor.
- Contact sections in the footer or newsletter sign-up buttons.
- Not a good fit: densely packed buttons such as table rows or toolbars, where the offset can make neighbors look like they overlap.
Installation
npx webberui@latest add https://webberui.com/r/magnetic-button.en.jsonInstalling also writes the --wb-duration-fast CSS variable into your global stylesheet.
Usage
import { MagneticButton } from "@/components/ui/magnetic-button";
<MagneticButton onClick={() => console.log("clicked")}>
Get started
</MagneticButton>Examples
Outline style
The default is a solid button. className merges with the default classes, so you can turn it into an outline button.
<MagneticButton className="border border-neutral-300 bg-transparent text-neutral-900 hover:bg-neutral-100 dark:border-neutral-700 dark:bg-transparent dark:text-neutral-100 dark:hover:bg-neutral-800">
View work
</MagneticButton>Tune the pull and the spring
A larger strength gives a bigger offset. springConfig takes Motion spring options; lowering damping makes the return wobble more.
<MagneticButton
strength={0.5}
springConfig={{ stiffness: 180, damping: 10, mass: 0.8 }}
className="px-8 py-4 text-base"
>
Book a consultation
</MagneticButton>As a form submit button
The component defaults to type="button"; passing type="submit" overrides it. Other native attributes such as disabled are forwarded as well, and the magnetic effect turns off while disabled.
<form action={subscribe} className="flex gap-2">
<input name="email" type="email" required placeholder="you@example.com" className="rounded-full border px-4" />
<MagneticButton type="submit" disabled={pending}>
Subscribe
</MagneticButton>
</form>Props
| Prop | Type | Default | Description |
|---|---|---|---|
strength | number | 0.35 | Magnet strength: the button's offset = the cursor's distance from center × strength; 0 means it does not move at all |
springConfig | SpringOptions | { stiffness: 260, damping: 18, mass: 0.7 } | Spring parameters for the return after the cursor leaves |
className | string | — | Overrides the default styles (a solid button by default, changeable to an outline or other variant) |
children | ReactNode | — | Button content |
All other <button> attributes (onClick, disabled, aria-*, and so on) are forwarded directly.
How it works
- Parallax depth: as the button shifts towards the cursor, the inner text shifts half as far in the opposite direction, producing a two-layer sense of depth
- Spring back: driven by
useMotionValue+useSpring, so it springs back to its original position with momentum once the cursor leaves - Disabled on touch devices automatically: it only responds to mouse pointer events (
pointerType === "mouse"), so on touch it is just an ordinary button - When the user has "reduce motion" enabled at the system level, the magnetism is disabled: the button stays put and functionality is unaffected
- The magnetism is also disabled while
disabled
FAQ
Does it work with the Next.js App Router?
Yes. The file starts with "use client", so import it from a Server Component page as usual.
How do I change the magnetic strength?
strength sets the offset: the button moves by the cursor's distance from its center multiplied by strength (default 0.35), and 0 disables movement. Tune the return feel with springConfig.
I also need onPointerMove. Will it be overridden?
No. The component calls your onPointerMove and onPointerLeave first, then runs its own magnetic logic.
What happens on phones and touch devices?
The effect only responds to mouse pointer events, so on touch it is a regular button. It is also turned off when the system "reduce motion" setting is on or the button is disabled.
What are the dependencies?
motion, clsx and tailwind-merge. If you prefer not to use the CLI, copy the source from the Manual tab in Installation.
Switch-to-Slider Morph
A React switch and slider that share one thumb: turning it on makes the thumb leap onto a vertical or horizontal slider to set a value, turning it off sends it back. Built for enable-then-adjust settings.
Theme Toggle
A light/dark theme toggle button: View Transitions expand a circle out from the click point, and the Sun/Moon icons rotate through the transition.