The problem
You want elements to smoothly follow the cursor creating an engaging magnetic interaction.
The solution
.magnetic-btn {
position: relative;
padding: 20px 40px;
font-size: 18px;
font-weight: 700;
color: white;
background: linear-gradient(135deg, #3a7bff 0%, #8b5cf6 100%);
border: none;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.23, 1, 0.320, 1);
overflow: hidden;
}
/* Glow effect */
.magnetic-btn::before {
content: '';
position: absolute;
inset: -2px;
background: linear-gradient(135deg, #3a7bff, #8b5cf6);
border-radius: 50px;
opacity: 0;
transition: opacity 0.3s;
z-index: -1;
filter: blur(10px);
}
.magnetic-btn:hover::before {
opacity: 0.8;
}
/* Shine effect */
.magnetic-btn::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.magnetic-btn:hover::after {
width: 300px;
height: 300px;
}
.magnetic-btn span {
position: relative;
z-index: 1;
}
/* Ripple on click */
@keyframes ripple {
0% {
transform: translate(-50%, -50%) scale(0);
opacity: 1;
}
100% {
transform: translate(-50%, -50%) scale(4);
opacity: 0;
}
}
.magnetic-btn:active::after {
animation: ripple 0.6s ease-out;
}See it live
Put it to work
<button class="magnetic-btn" onmousemove="magneticMove(event)" onmouseleave="magneticReset(event)">
<span>Magnetic Button</span>
</button>
<script>
function magneticMove(e) {
const btn = e.currentTarget;
const rect = btn.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
const moveX = x * 0.3;
const moveY = y * 0.3;
btn.style.transform = `translate(${moveX}px, ${moveY}px) scale(1.05)`;
}
function magneticReset(e) {
e.currentTarget.style.transform = 'translate(0, 0) scale(1)';
}
</script>Worth knowing
Multiply cursor offset by a factor (0.3) for smooth magnetic effect. Use cubic-bezier for fluid motion.