<div class="magnet-area" id="magnet-area">
<a href="#" class="magnet-btn" id="magnet-btn">
<span class="btn-text" id="btn-text">Hover Me</span>
</a>
</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: #f8fafc;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.magnet-area {
width: 300px;
height: 300px;
display: flex;
justify-content: center;
align-items: center;
/* Helpful border just for visualizing the trigger zone */
border: 1px dashed #cbd5e1;
border-radius: 50%;
}
.magnet-btn {
display: flex;
justify-content: center;
align-items: center;
width: 140px;
height: 140px;
background: #0f172a;
color: #ffffff;
border-radius: 50%;
text-decoration: none;
font-weight: 700;
font-size: 1.1rem;
letter-spacing: 1px;
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
will-change: transform;
}
.btn-text {
pointer-events: none;
transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1);
}
const area = document.getElementById("magnet-area");
const btn = document.getElementById("magnet-btn");
const text = document.getElementById("btn-text");
area.addEventListener("mousemove", function(e) {
const rect = area.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
/* Calculate distance from center */
const deltaX = e.clientX - centerX;
const deltaY = e.clientY - centerY;
/* Apply a fraction of the distance to the button (pulls it toward cursor) */
btn.style.transform = "translate(" + (deltaX * 0.4) + "px, " + (deltaY * 0.4) + "px)";
/* Apply an even smaller fraction to the text to create a parallax depth effect */
text.style.transform = "translate(" + (deltaX * 0.15) + "px, " + (deltaY * 0.15) + "px)";
});
area.addEventListener("mouseleave", function() {
/* Snap back elegantly */
btn.style.transition = "transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1)";
text.style.transition = "transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1)";
btn.style.transform = "translate(0px, 0px)";
text.style.transform = "translate(0px, 0px)";
});
area.addEventListener("mouseenter", function() {
/* Remove transition to allow instant physics tracking */
btn.style.transition = "none";
text.style.transition = "none";
});