Crafting Premium Micro-Interactions & Brutalist Animations with Framer Motion
How to craft magnetic cursor buttons, smooth layout morphing, parallax scroll animations, and scroll-driven physics without dropping frames.
High-end digital experiences distinguish themselves through the quality of their micro-interactions. In my portfolio, subtle physics-based cursor magnetism and scroll transitions give the interface a tactile, engaging feel.
1. Magnetic Button Implementation
"use client";
import { useRef, useState } from "react";
import { motion } from "framer-motion";
export function MagneticButton({ children }: { children: React.ReactNode }) {
const ref = useRef<HTMLDivElement>(null);
const [position, setPosition] = useState({ x: 0, y: 0 });
function handleMouseMove(e: React.MouseEvent<HTMLDivElement>) {
const { clientX, clientY } = e;
const { left, top, width, height } = ref.current!.getBoundingClientRect();
const middleX = clientX - (left + width / 2);
const middleY = clientY - (top + height / 2);
setPosition({ x: middleX * 0.25, y: middleY * 0.25 });
}
function handleMouseLeave() {
setPosition({ x: 0, y: 0 });
}
return (
<motion.div
ref={ref}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
animate={{ x: position.x, y: position.y }}
transition={{ type: "spring", stiffness: 150, damping: 15, mass: 0.1 }}
className="inline-block"
>
{children}
</motion.div>
);
}2. Scroll-Driven Parallax
Using useScroll and useTransform allows hardware-accelerated transforms on the compositor thread without causing repaints:
import { useScroll, useTransform, motion } from "framer-motion";
export function ParallaxHero() {
const { scrollY } = useScroll();
const y = useTransform(scrollY, [0, 500], [0, 150]);
const opacity = useTransform(scrollY, [0, 300], [1, 0]);
return (
<motion.div style={{ y, opacity }} className="will-change-transform">
<h1>MAULANA</h1>
</motion.div>
);
}Micro-interactions should feel effortless, responsive, and purposeful.