Build smooth, delightful UIs using advanced techniques and modern animation tools.
Welcome to the world of declarative animations in React! Framer Motion is a powerful library that makes creating smooth, performant animations a breeze. Whether you're building UI transitions or adding subtle interactions, this chapter will teach you everything you need to know to create beautiful and accessible animations.
Framer Motion is a declarative animation library for React. It provides a simple, yet powerful way to add animations to your components without getting lost in complex APIs or performance pitfalls.
Let's start by setting up Framer Motion in your project. You'll need to install it using npm or yarn.
npm install framer-motion
# or
yarn add framer-motion
Now that Framer Motion is installed, you can start using it in your components.
Framer Motion provides a motion component that wraps any React element and adds animation capabilities. Here's how to create a basic animation.
import { motion } from 'framer-motion';
function MyComponent() {
return (
<motion.div
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.5 }}
>
Hello, World!
</motion.div>
);
}
In this example: - The initial prop defines the starting state. - The animate prop defines the end state. - The transition prop controls how the animation is performed.
When working with layouts that change dynamically (like lists or grids), layout transitions can help create a smooth experience. Framer Motion provides the layoutId and AnimatePresence components to handle these cases.
import { motion, AnimatePresence } from 'framer-motion';
function List() {
const items = ['Item 1', 'Item 2', 'Item 3'];
return (
<motion.div layoutId="list">
{items.map((item) => (
<motion.div key={item} layoutId={item}>
{item}
</motion.div>
))}
</motion.div>
);
}
The layoutId prop helps Framer Motion understand how elements should transition between different states. Using AnimatePresence, you can animate components when they enter or exit the DOM.
Animations can be resource-intensive if not handled properly. Here are some tips to ensure your animations run smoothly:
Animations can enhance user experience, but they should never come at the cost of accessibility. Here are some best practices:
Now that you've learned the basics, let's see how Framer Motion can be used in real-world applications. From simple hover effects to complex loading animations, the possibilities are endless!
In this chapter, we'll explore three powerful React concepts: Portals, Refs, and Imperative Code. These tools allow you to create more dynamic and interactive user interfaces while maintaining control over your components.
Portals provide a way to render React components outside of your current DOM hierarchy. This is particularly useful for creating overlays, modals, or tooltips that need to appear above other elements.
import { createPortal } from 'react';
export default function Modal({ children }) {
return createPortal(
<div className="modal-overlay">
<div className="modal-content">{children}</div>
</div>,
document.getElementById('portal-root')
);
}
Refs provide a way to directly access DOM elements or other React components. They are particularly useful when you need to control elements imperatively.
import { useRef, useEffect } from 'react';
export default function Timer() {
const timerRef = useRef(null);
useEffect(() => {
const interval = setInterval(timerRef.current.textContent = new Date().toLocaleTimeString();
return () => clearInterval(interval);
}, 1000);
return <div ref={timerRef}></div>;
}
When creating custom hooks or components, you may want to forward refs to underlying elements. This can be done using forwardRef and useImperativeHandle.
import { forwardRef, useImperativeHandle } from 'react';
export default function CustomInput({ ...props }, ref) {
const [value, setValue] = useState('');
useImperativeHandle(ref, () => ({
setValue,
getValue: () => value
}));
return (
<input
ref={ref}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}
Question 1 of 10