<div class="magnetic-wrap">
<button id="mag-btn" class="magnetic-btn">
Hover Me
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</button>
</div>
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
margin: 0;
background: #f3f4f6;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.magnetic-wrap {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 300px;
}
.magnetic-btn {
background: #111827;
color: #ffffff;
border: none;
padding: 16px 32px;
border-radius: 30px;
font-weight: 600;
font-size: 1.125rem;
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2);
will-change: transform;
}
const magBtn = document.getElementById("mag-btn");
magBtn.addEventListener("mouseenter", function() {
magBtn.style.transition = "none";
});
magBtn.addEventListener("mousemove", function(e) {
const rect = magBtn.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
// Multiply by 0.3 so the button moves gently, not all the way to the cursor
magBtn.style.transform = "translate(" + (x * 0.3) + "px, " + (y * 0.3) + "px)";
});
magBtn.addEventListener("mouseleave", function() {
// Snap back smoothly when the cursor leaves
magBtn.style.transition = "transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1)";
magBtn.style.transform = "translate(0px, 0px)";
});