Mini curso · 01

Botón magnético

Ese botón que se “despega” hacia tu cursor cuando te acercas y da la sensación de que quiere que lo pulses. Se hace con dos ideas simples: distancia y transform.

CSS transform JavaScript Dificultad baja ⏱ 5 min

Acerca el mouse al botón y juega con los controles 👇

mueve el cursor cerca del botón

Fíjate: con fuerza 0 el botón no se mueve; con fuerza 1 se pega al cursor. El radio decide desde qué distancia empieza a reaccionar.

La idea en una frase

Un botón magnético mide cuánto se aleja el cursor del centro del botón y mueve el botón esa misma distancia, pero solo una fracción. Esa fracción es la “fuerza” del imán. Nada de física complicada: pura resta y multiplicación.

const dx = cursorX - centroX;
const dy = cursorY - centroY;
boton.style.transform = `translate(${dx * 0.40}px, ${dy * 0.40}px)`;

Ese 0.40 es exactamente el slider “Fuerza” de arriba — muévelo y mira cómo cambia el número aquí en el código en tiempo real.

Paso 1 · El HTML

Solo necesitas el botón. Nada especial:

<button class="iman">Atráeme</button>

Paso 2 · El CSS

La clave es will-change: transform (le avisa al navegador que este elemento se va a mover, para que lo haga fluido en la GPU) y una transition para que el regreso sea suave.

.iman{
  padding:.9rem 1.6rem;
  border-radius:999px;
  background:#17a2b8; color:#fff;
  will-change:transform;
  transition:transform .25s ease;
}

Paso 3 · El JavaScript

Escuchamos mousemove sobre el botón, calculamos la distancia al centro y aplicamos el transform. Al salir (mouseleave) lo devolvemos a su sitio limpiando el estilo.

const boton = document.querySelector('.iman');
const fuerza = 0.4;

boton.addEventListener('mousemove', e => {
  const r = boton.getBoundingClientRect();
  const dx = e.clientX - (r.left + r.width  / 2);
  const dy = e.clientY - (r.top  + r.height / 2);
  boton.style.transform = `translate(${dx*fuerza}px, ${dy*fuerza}px)`;
});

boton.addEventListener('mouseleave', () => {
  boton.style.transform = '';
});

El detalle que lo hace “pro”

El truco final es esa transition en el CSS. Mientras el cursor está encima, el transform se actualiza tan seguido que el botón parece pegado al mouse (la transición no alcanza a notarse). Pero al salir, como limpiamos el transform de golpe, la transición actúa y el botón regresa con un rebote suave. Ese contraste es lo que se siente “vivo”.

Bonus · activarlo solo cuando estás cerca

En el playground de arriba añadimos un radio: el imán solo actúa si el cursor está a menos de X píxeles. Es una línea más:

const dist = Math.hypot(dx, dy);
if (dist < 140) {
  boton.style.transform = `translate(${dx*fuerza}px, ${dy*fuerza}px)`;
} else {
  boton.style.transform = '';
}

Y eso es todo 🎉

Con distancia + transform + una transición tienes un botón magnético. La misma idea (mover algo una fracción hacia el cursor) es la base del cursor personalizado, los seguidores con lerp y hasta la mascota de la portada.