Back to Blog

Framer Motion Tutorial: 5 Advanced Animation Patterns

The UI Factory

Framer Motion Tutorial: Advanced Patterns

Framer Motion is the undisputed champion of animation in the React ecosystem. While simple animate={{ opacity: 1 }} properties are easy to grasp, mastering physics-based micro-interactions is what separates amateur interfaces from premium ones.

In this tutorial, we will explore advanced patterns we use heavily at The UI Factory.

Pattern 1: The "Magnetic" Hover Effect

This effect makes an element seemingly stick to the user's cursor when they hover over it, creating a strong physical connection.

import { motion, useMotionValue, useSpring, useTransform } from "framer-motion";
import { useRef } from "react";

export const MagneticButton = ({ children }) => {
  const ref = useRef(null);
  const x = useMotionValue(0);
  const y = useMotionValue(0);

  // Add physics to the movement
  const springX = useSpring(x, { stiffness: 150, damping: 15, mass: 0.1 });
  const springY = useSpring(y, { stiffness: 150, damping: 15, mass: 0.1 });

  const handleMouseMove = (e) => {
    const { clientX, clientY } = e;
    const { height, width, left, top } = ref.current.getBoundingClientRect();
    const centerX = left + width / 2;
    const centerY = top + height / 2;
    
    // Pull the button towards the cursor (but only slightly)
    x.set((clientX - centerX) * 0.2);
    y.set((clientY - centerY) * 0.2);
  };

  const handleMouseLeave = () => {
    x.set(0);
    y.set(0);
  };

  return (
    <motion.button
      ref={ref}
      onMouseMove={handleMouseMove}
      onMouseLeave={handleMouseLeave}
      style={{ x: springX, y: springY }}
      className="px-8 py-4 bg-black text-white rounded-full font-bold"
    >
      {children}
    </motion.button>
  );
};

Pattern 2: Spring-Loaded Brutalism

In the Ink & Acid design system, we replace soft easings with aggressive, spring-loaded physics.

<motion.button
  whileHover={{ scale: 1.05, boxShadow: "8px 8px 0px #000" }}
  whileTap={{ scale: 0.95, boxShadow: "0px 0px 0px #000" }}
  transition={{ type: "spring", stiffness: 400, damping: 17 }}
  className="bg-[#ccff00] border-4 border-black"
>
  Click Me
</motion.button>

The high stiffness (400) and low damping (17) create a violent, satisfying snap back into place, mimicking a heavy mechanical switch.

Explore the components gallery to see these animations in action!