Quick Answer: Engineering UI Animations with Framer Motion#
transform: translate3d/scale and opacity), layoutId shared element transitions, and AnimatePresence exit lifecycles, developers can build fluid, app-like micro-interactions that never block the main JavaScript thread or cause Cumulative Layout Shift (CLS).
The Golden Rule of 60fps Web Animations#
Most web animations feel sluggish or jittery because developers animate CPU-heavy CSS properties (such as width, height, top, margin, or box-shadow). These properties trigger full browser Reflow & Repaint cycles on every frame.
#High-Performance vs Low-Performance Properties:
1. Spring Physics vs. Linear Duration Curves#
Real-world objects do not stop abruptly with mechanical ease-in-out timing curves; they possess mass, stiffness, and damping.
Framer Motion utilizes spring physics by default:
import { motion } from 'framer-motion';
export function InteractiveCard({ title, subtitle }: { title: string; subtitle: string }) {
return (
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-50px' }}
whileHover={{ scale: 1.03, y: -6 }}
whileTap={{ scale: 0.97 }}
transition={{
type: 'spring',
stiffness: 300, // Speed of the spring snap
damping: 20, // Resistance preventing endless oscillation
mass: 0.8,
}}
className="p-8 rounded-3xl glass border border-white/10 shadow-2xl cursor-pointer"
>
<h3 className="text-2xl font-black text-white">{title}</h3>
<p className="text-sm text-foreground/60 mt-2">{subtitle}</p>
</motion.div>
);
}
2. Magic Shared Element Transitions (layoutId)#
When navigating between tabs or expanding a modal from a small card, Framer Motion automatically calculates the bounding box difference and morphs the element seamlessly:
'use client';
import { useState } from 'react';
import { motion } from 'framer-motion';
const TABS = ['Architecture', 'DevOps', 'AI Agents'];
export function AnimatedTabs() {
const [activeTab, setActiveTab] = useState(TABS[0]);
return (
<div className="flex gap-2 p-1.5 rounded-full bg-white/5 border border-white/10 w-fit">
{TABS.map((tab) => {
const isActive = activeTab === tab;
return (
<button
key={tab}
onClick={() => setActiveTab(tab)}
className="relative px-6 py-2.5 text-xs font-bold font-mono uppercase tracking-wider text-white transition-colors"
>
{isActive && (
<motion.div
layoutId="active-pill"
transition={{ type: 'spring', stiffness: 400, damping: 30 }}
className="absolute inset-0 bg-primary rounded-full shadow-lg -z-10"
/>
)}
<span className={isActive ? 'text-white' : 'text-foreground/50 hover:text-white'}>
{tab}
</span>
</button>
);
})}
</div>
);
}
3. Scroll-Linked Parallax with useScroll & useTransform#
Create immersive hero sections where UI elements float at varying speeds as the user scrolls:
'use client';
import { useRef } from 'react';
import { motion, useScroll, useTransform } from 'framer-motion';
export function ParallaxHero() {
const containerRef = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ['start start', 'end start'],
});
const textY = useTransform(scrollYProgress, [0, 1], ['0%', '120%']);
const opacity = useTransform(scrollYProgress, [0, 0.8], [1, 0]);
const scale = useTransform(scrollYProgress, [0, 1], [1, 0.85]);
return (
<div ref={containerRef} className="h-screen relative flex items-center justify-center overflow-hidden">
<motion.div style={{ y: textY, opacity, scale }} className="text-center max-w-3xl z-10 px-6">
<h1 className="text-6xl font-black text-white tracking-tight">
Engineering the <span className="text-gradient">Future</span>
</h1>
</motion.div>
</div>
);
}
4. Exit Animations with AnimatePresence#
React unmounts components from the DOM immediately when state changes. AnimatePresence intercepts the unmount to run smooth exit animations:
import { motion, AnimatePresence } from 'framer-motion';
export function NotificationToast({ isVisible, message }: { isVisible: boolean; message: string }) {
return (
<AnimatePresence>
{isVisible && (
<motion.div
initial={{ opacity: 0, y: -20, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: -20, scale: 0.95 }}
transition={{ duration: 0.2 }}
className="fixed top-6 right-6 p-4 rounded-2xl glass border border-primary/30 text-white font-bold"
>
{message}
</motion.div>
)}
</AnimatePresence>
);
}
Craft Premium Digital Experiences with Rajput Bhavin Engineering#
We design websites and SaaS platforms that feel alive, responsive, and memorable.
- ✦Explore our Website Redesign Services
- ✦Discover our Tailwind CSS v4.0 Guide
- ✦Schedule a Design & Engineering Consultation with Rajput Bhavin today.