Modals are a common UI element in web applications, used to display additional content or options without navigating away from the current page. Adding animations to modals can greatly improve the user experience by making the transitions feel smoother and more dynamic. In this guide, we’ll walk through how to create animated modals in React, using Framer Motion for the animations.
1. Setting Up the Project
First, make sure you have a React project. If you don’t have one already, you can create it using create-react-app
:
npx create-react-app animated-modals
cd animated-modals
Now, install Framer Motion for animation support:
npm install framer-motion
2. Basic Structure of a Modal in React
A modal in React typically consists of three main parts:
- A modal container (which covers the screen).
- The modal content (which holds the modal’s content).
- A close button (to dismiss the modal).
Here’s a basic modal component without animation:
import React, { useState } from 'react';
const Modal = ({ isOpen, onClose }) => {
if (!isOpen) return null;
return (
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
<h2>Modal Title</h2>
<p>This is some content inside the modal!</p>
<button onClick={onClose}>Close</button>
</div>
</div>
);
};
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);
return (
<div>
<button onClick={openModal}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={closeModal} />
</div>
);
};
export default App;
In this basic example:
- The
Modal
component is conditionally rendered based on theisOpen
prop. - Clicking on the overlay or the close button triggers the
onClose
function to close the modal.
3. Adding Framer Motion Animations
Now, let’s enhance the modal with animations using Framer Motion. We’ll animate the modal’s appearance (fade in and scale up) when it opens, and make it fade out when it closes.
Update the Modal
Component:
import React from 'react';
import { motion } from 'framer-motion';
const Modal = ({ isOpen, onClose }) => {
if (!isOpen) return null;
return (
<motion.div
className="modal-overlay"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
onClick={onClose}
>
<motion.div
className="modal-content"
initial={{ scale: 0.8 }}
animate={{ scale: 1 }}
exit={{ scale: 0.8 }}
transition={{ duration: 0.3 }}
onClick={(e) => e.stopPropagation()}
>
<h2>Modal Title</h2>
<p>This is some content inside the modal!</p>
<button onClick={onClose}>Close</button>
</motion.div>
</motion.div>
);
};
export default Modal;
Explanation of Animation:
motion.div
: We usemotion.div
from Framer Motion to animate both the modal overlay and content.initial
,animate
,exit
: These are Framer Motion’s animation states.initial
defines the starting state when the modal appears.animate
defines the final state when the modal is fully visible.exit
defines the state when the modal is removed (during closing).
transition
: This controls the duration and easing of the animations.
4. Adding Styling
Let’s style the modal so it looks better.
/* App.css */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0px 4px 15px rgba(0, 0, 0, 0.2);
max-width: 500px;
width: 100%;
}
button {
padding: 10px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
5. Animating Modal Close Action
Next, let’s handle the close animation. We want the modal to fade and scale down when it’s closed. We’ve already defined the exit animation for the modal content in the Modal
component. However, we also need to make sure that the modal closes smoothly when the user clicks outside the modal or presses the close button.
Since we’ve already defined the exit
state for the modal content, Framer Motion will handle the exit animation for us. By wrapping the modal content and overlay in motion.div
, it will automatically trigger the exit animation when the modal is removed from the DOM.
6. Final Code
import React, { useState } from 'react';
import Modal from './Modal';
import './App.css';
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);
return (
<div>
<button onClick={openModal}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={closeModal} />
</div>
);
};
export default App;