Thursday, October 23, 2025
HomeLanguagesAnimated modal using react, framer-motion & styled-components

Animated modal using react, framer-motion & styled-components

In this article, we are going to learn how to create an animated modal using react, framer-motion & styled-components.

Prerequisites:

  1. Knowledge of JavaScript (ES6).
  2. Knowledge of HTML/CSS.
  3. Basic knowledge of ReactJS.

Framer-motion: The components and attributes we are going to make use of in this tutorial.

  1. https://www.framer.com/api/motion/component/
  2. https://www.framer.com/api/motion/animate-presence/

Creating React Application And Installing Module :

Step 1: Now, you will start a new project using create-react-app so open your terminal and type.

npx create-react-app toggle-modal

Step 2: After creating your project folder i.e. toggle-modal, move to it using the following command.

cd toggle-modal

Step 3: Add the npm packages you will need during the project.

npm install framer-motion styled-components
//For yarn
yarn add framer-motion styled-components

Step 5: Now open your newly created project with your favorite code editor, I am using Visual Studio Code and will recommend you to use the same.

Open the src folder and delete the following files:

  1. logo.svg
  2. serviceWorker.js
  3. setupTests.js
  4. index.css
  5. App.test.js (if any)

Create a file named Styles.js.

Project structure: Your folder structure tree should look like this.

Project structure

Approach:

  • We are going to create a Modal component with ‘showModal’ prop only to manage its state of visibility and animated using framer-motion AnimatePresence.
  • AnimatePresence allows components to animate out when they’re removed from the React tree and to enable exit animations.
  • To give spring animation to modal container we will use framer-motion spring animation with stiffness = 300.
  • Content of modal is neveropen image which is also animated using framer-motion motion.div.
  • React useState hook to manage the state of ‘showModal’ i.e. responsible to toggle the modal container.
  • ‘displayModal’ utility function to set the ‘showModal’ value opposite of its last value to toggle modal.
  • Event listener for document body so that on clicking outside or on the modal, ‘showModal’ is set to false and in turn modal is disappeared.
  • ToggleBtn is also animated using framer-motion motion.button.

Example:

Styles.js




import styled from "styled-components";
import { motion } from "framer-motion";
  
export const ModalBox = styled(motion.div)`
  position: relative;
  z-index: 2;
  width: 400px;
  height: 200px;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #fff;
`;
  
export const ModalContent = styled(motion.div)`
  padding: 5px;
`;
  
export const ModalContainer = styled.div`
  height: 100vh;
  background: #111;
  display: flex;
  flex-direction: column;
  align-items: center;
`;
  
export const ToggleBtn = styled(motion.button)`
  cursor: pointer;
  font-size: 20px;
  color: #fff;
  padding: 0.5rem 0.8rem;
  margin-top: 3rem;
  background: #3bb75e;
  text-decoration: none;
  border: none;
  border-radius: 50px;
`;


App.js




import React, { useState } from "react";
import { AnimatePresence } from "framer-motion";
import { ToggleBtn, ModalBox, ModalContent, ModalContainer } from "./Styles";
import "./App.css";
  
// Modal component with 'showModal' prop only
// to manage its state of visibility and
// animated using framer-motion
const Modal = ({ showModal }) => {
  return (
    <ModalContainer>
      <AnimatePresence>
        {showModal && (
          <ModalBox
            initial={{ opacity: 0, 
                       y: 60, scale: 0.5 }}
            animate={{
              opacity: 1,
              y: 0,
              scale: 1,
              // making use of framer-motion spring animation
              // with stiffness = 300
              transition: { type: "spring", 
                            stiffness: 300 }
            }}
            exit={{ opacity: 0, scale: 0.5, 
                    transition: { duration: 0.6 } }}>
            <ModalContent
              initial={{ y: -30, opacity: 0 }}
              animate={{ y: 0, opacity: 1, 
                         transition: { delay: 0.5 } }}>
              {/* Modal content is neveropen image */}
              <img
                src="Modal image link"
                alt="neveropen"
              />
            </ModalContent>
          </ModalBox>
        )}
      </AnimatePresence>
    </ModalContainer>
  );
};
  
const App = () => {
  // React useState hook to manage the state of 'showModal'
  // i.e. responsible to toggle the modal container
  const [showModal, setShowModal] = useState(false);
  
  // utility function to set the showModal value
  // opposite of its last value
  // to toggle modal
  const displayModal = () => {
    setShowModal(!showModal);
    document.getElementById("btn").style.visibility = "hidden";
  };
  
  // event listener for document body
  // so that on clicking outside the modal,
  // 'showModal' is set to false.
  document.body.addEventListener("click", () => {
    if (showModal) {
      setShowModal(false);
    }
  });
  
  return (
    <ModalContainer>
      <ToggleBtn
        id="btn"
        initial={{ x: -700 }}
        animate={{
          x: 0,
          transition: { duration: 0.1 }
        }}
        // event listener for the toggle button
        // to display modal on click
        onClick={displayModal}>
        Toggle Modal
      </ToggleBtn>
      {/* passing 'showModal' as a prop to Modal component */}
      <Modal showModal={showModal} />
    </ModalContainer>
  );
};
  
export default App;


index.js




import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
  
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);


App.css




* {
  margin: 0;
  box-sizing: border-box;
}
  
img {
  padding: 5px;
  width: 400px;
  overflow: hidden;
}


Step to Run Application: Run the application using the following command from the root directory of the project.

npm start

Output: Now open your browser and go to http://localhost:3000/, you will see the following output.

Whether you’re preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape, neveropen Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we’ve already empowered, and we’re here to do the same for you. Don’t miss out – check it out now!
RELATED ARTICLES

Most Popular

Dominic
32361 POSTS0 COMMENTS
Milvus
88 POSTS0 COMMENTS
Nango Kala
6728 POSTS0 COMMENTS
Nicole Veronica
11892 POSTS0 COMMENTS
Nokonwaba Nkukhwana
11954 POSTS0 COMMENTS
Shaida Kate Naidoo
6852 POSTS0 COMMENTS
Ted Musemwa
7113 POSTS0 COMMENTS
Thapelo Manthata
6805 POSTS0 COMMENTS
Umr Jansen
6801 POSTS0 COMMENTS