Magnetic button: a hover effect that pulls toward your cursor
A button that leans toward your mouse as it comes close, and springs back when you leave. Bring your pointer near it to try.
UI loop
A button that pulls you in
Sundry Millsundrymill.com/library
Everything in the preview is live. Try it.
The code
Magnetic button
The button leans toward your mouse inside an invisible zone around it. Touch screens leave it still.
HTML
<div class="mag" data-magnetic>
<button class="mag-btn" type="button"><span>Get started</span></button>
</div>
CSS
.mag { display: inline-grid; place-items: center; padding: 40px; }
.mag-btn {
padding: 16px 28px;
border: 0;
border-radius: 999px;
background: #17202C;
color: #FDF9F1;
font: inherit;
font-weight: 700;
cursor: pointer;
transform: translate(var(--mx, 0px), var(--my, 0px));
transition: transform .6s cubic-bezier(.05, .7, .1, 1);
}
.mag-btn span {
display: inline-block;
transform: translate(calc(var(--mx, 0px) * .4), calc(var(--my, 0px) * .4));
transition: transform .6s cubic-bezier(.05, .7, .1, 1);
}
.mag.is-near .mag-btn, .mag.is-near .mag-btn span { transition-duration: .15s; }
JavaScript
const PULL = 0.35; // how far the button follows, 0 to 1
document.querySelectorAll('[data-magnetic]').forEach((zone) => {
const btn = zone.querySelector('.mag-btn');
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;
zone.addEventListener('pointermove', (e) => {
if (e.pointerType !== 'mouse') return;
const r = zone.getBoundingClientRect();
zone.classList.add('is-near');
btn.style.setProperty('--mx', ((e.clientX - (r.left + r.width / 2)) * PULL).toFixed(1) + 'px');
btn.style.setProperty('--my', ((e.clientY - (r.top + r.height / 2)) * PULL).toFixed(1) + 'px');
});
zone.addEventListener('pointerleave', () => {
zone.classList.remove('is-near');
btn.style.removeProperty('--mx');
btn.style.removeProperty('--my');
});
});
How to use it
- The zone around the button is the padding on the wrapper. Make it bigger for a stronger pull from further away.
- PULL sets how far the button follows the pointer. 0.2 is subtle, 0.5 is playful.
- It only reacts to a mouse. On touch screens the button stays put, which is what you want.
Showing an interaction like this to a client or in a tutorial? Framok records your screen and zooms in on every click for you.
Free to use in personal and commercial work. No credit needed, though a link back is always nice.