DEV Community

Swislok-Dev
Swislok-Dev

Posted on

Animated Modal in React

This will be a guide to setting up a modal that will pop in the center of the screen.

Create a Modal Component

import React from "react"

function Modal(props) {
  return (
    <div className="modal">
      <div className="modal-content">
        <div className="modal-header">
          <h4 className="modal-title">Modal Title</h4>
        </div>
        <div className="modal-body">Modal Body</div>
        <div className="modal-footer">
          <button className="button">Close</button>
        </div>
      </div>
    </div>
  )
};

export default Modal
Enter fullscreen mode Exit fullscreen mode

Style the Modal

/* Modal */

.modal {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-content {
  width: 500px;
  background-color: #fff;
}

.modal-header, .modal-footer {
  padding: 10px;
}

.modal-body {
  padding: 10px;
  border-top: 1px solid #eee;
  border-bottom: 1px solid #eee;
}
Enter fullscreen mode Exit fullscreen mode

Import to App.js

import React from "react"
import Modal from "./components/Modal/Modal"

function App() {
  return (
    <div className="App">
      <button >Show Modal</button>
      <Modal />
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Show the modal

When the Show Modal button is pressed the modal should pop up.

Using state will allow the modal to show or be hidden depending on the current state. In Modal.js, add the following prop check for if the modal should be shown.

// Modal.js

function Modal(props) {
  if (!props.show) {
    return null
  }

...

}
Enter fullscreen mode Exit fullscreen mode

Using useState add a state object to App.js:

import React, { useState } from "react"
import Modal from "./components/Modal/Modal.jsx"
import "./App.css"

function App() {
  const [show, setShow] = useState(false)
  return (
    <div className="App">
      <h1>Scratch Pad</h1>
      <button onClick={() => setShow(true)}>Show Modal</button>
      <Modal show={show}/>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Hide the modal

Update the following code to implement a way to close the modal without the need for a function by changing state props.

// App.js

<button onClick={() => setShow(true)}>Show Modal</button>
<Modal onClose={() => setShow(false)} show={show} />
Enter fullscreen mode Exit fullscreen mode
// Modal.js

<div className="modal-footer">
  <button onClick={props.onClose} classname="button">Close</button>
</div>
Enter fullscreen mode Exit fullscreen mode

Close modal on outside click

We should add a way for the modal to close on its own when clicked off the modal.

Functionality will remain as expected, ability to click content on the modal without closing, and be able to close by clicking the close button or off the modal.

// Modal.js

return (
  <div className="modal" onClick={props.onClose}>
    <div className="modal-content" 
         onClick={(e) => e.stopPropagation()}>
      ...
    </div>
  </div>
)
Enter fullscreen mode Exit fullscreen mode

The modal should close when clicked outside of the modal content box, but do nothing when clicked inside.

Now to give it a drop-in animation

Animate the modal

Add in the following to give the modal a drop down animation when it has been opened.

.modal {
  ...
  opacity: 0;
  transition: all 0.3s ease-in-out;
  pointer-events: none;
}

.modal.show {
  opacity: 1;
  pointer-events: visible;
}

.modal-content {
  ...
  transform: translateY(-200px);
  transition: all 0.3s ease-in-out;
}

.modal-show .modal-content {
  transform: translateY(0);
}
Enter fullscreen mode Exit fullscreen mode

And finally using useState hook handle the .show class.

// Modal.js

function Modal(props) {
  // if (!props.show) { return null } should be removed.
  return (
    <div className={`modal ${props.show ? "show" : ""}`} onClick={props.onClose}>
    ...
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

The null check should be removed since the show/hide functionality is being handled through CSS now.

And now you have a modal with a slight animation. Play with the transition/transform settings to make it behave in the manner that you wish.

back to top

Top comments (0)