How To Build A Modal in React

Modals are important components of any application. Based on its implementation on a page, it allows an activity to be performed without the app user navigating to another page on the website. Be it for data collection in a form, custom message that an action have been performed, or a confirmation, It's use in an application is important.

This article walks you through a way to build a modal in react.

We first generate the folder for our project with create-react-app. We create a component folder. This is where we would keep our components(We are only creating one in this project). We would also create a modal subfolder, inside which we would create two files - Modal.js and Modal.css.

In the Modal. Js File we can go ahead and create a functional component named Modal and export appropriately.

import React from 'react'
import './Modal.css'

const Modal = () => {
    return (
        <div className="modal-container">

        </div>
    )
}

export default Modal

Let us create the Modal card itself. Inside the div with class "modal-container", we create another div with class "modal-wrapper". We want the modal card to have a header and content section. So we would have two divs inside the modal-wrapper div, with classes "modal-header" and "modal-content", respectively.

<div className="modal-container">
            <div className="modal-wrapper">
                <div className="modal-header">
                </div>

                <div className="modal-content">
                </div>                   
            </div>
</div>

In the modal-header div, we add our content and a button to close the modal. We add the content inside a p tag and we use a span tag for the button.

In the div with class modal-content, let us add two div tags, with classes "modal-body" and "modal-footer". In the div with class "modal-body", we can go ahead and include an h4 tag and a p tag. While in the div tag with class "modal-footer", we can include a button with class "button cancel".

<div className="modal-container">
        <div className="modal-wrapper">

                <div className="modal-header">
                    <p>Glad You Are Here</p>
                    <span className="close-modal-btn">x</span>
                </div>

                <div className="modal-content">
                    <div className="modal-body">
                            <h4>Modal</h4>
                           <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Impedit tempora labore fuga officiis. Odio sed esse porro corporis pariatur cumque.</p>
                    </div>

                    <div className="modal-footer">
                        <button className="btn-cancel">Close</button>
                    </div>
                </div>                   
        </div>
</div>

Let us move on to styling the modal card. We would do this in a Modal.css file inside the modal folder(For organization purpose let the Modal.js and Modal.css be inside the same folder, modal).

We start by setting all margins and paddings to zero and the font family to Montserrat.

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body{
    font-family: 'Montserrat', Helvetica, sans-serif;
}

We style the div with class "modal-wrapper". We set the witdh to 80% of the screen. and the maximum width to 800px. We centralize the card by setting the margin top and bottom to 4rem and left and right to auto. We then set the box shadow. We can generate a box-shadow automatically by visiting cssmatic/box-shadow.

.modal-wrapper{
    background-color: #fff;
    width: 80%;
    max-width: 800px;
    margin: 4rem auto;
    transition: all 0.3s ease;
    border-radius: 1rem;

    -webkit-box-shadow: -1px 1px 5px 0px rgba(0,0,0,0.75);
    -moz-box-shadow: -1px 1px 5px 0px rgba(0,0,0,0.75);
    box-shadow: -1px 1px 5px 0px rgba(0,0,0,0.75);
}

We would go on and add the other styling for the remaining part of the card. See code below.

.modal-header{
    background-color: #218491;
    color: #e9e9e9;
    font-size: 1.5rem;
    padding: 1rem;
    display: flex;
    align-items: center;
    border-radius: 1rem 1rem 0 0;
    justify-content: space-between;

}

.modal-header span {
    font-size: 1.5rem;
    cursor: pointer;
}

.modal-content {
    padding: 1.5rem 1rem;
}

.modal-body {
    margin-bottom: 1rem;
}

.modal-body h4 {
    font-size: 1.8rem;
    color: #218491;
}

.modal-body {
    font-size: 1rem;
    background: #eee;
    color: #333;
    padding: 1rem;
    margin: 1rem 0 2rem 0;
}

.modal-footer button{
    display: block;
    font-size: 1rem;
    margin-left: auto;
    padding: 0.5rem 1.8rem;
    background: #218491;
    color: #fff;
    border: none;
    outline: none;
    cursor: pointer;
    border-radius: 1rem;   
}

We create a styling for the modal backdrop with the code below.

.back-drop{
    background-color: rgba(63,61,61,0.692);
    height: 100%;
    position: fixed;
    width: 100%;
    top: 0;
    left: 0;
    transition: all 0.3s;
}

Now that we are done with the styling of the modal card, let us go back to the App component. We need to manage the display of the card on button click, so we need to add a button in the App component.

    <div>
      <button className="btn-openModal">Open Modal</button>
      <Modal />
    </div>

Also the see the button styling below.

.btn-openModal{
    background: #218491;
    color: #eee;
    margin: 2rem;
    padding: 0.9rem 1.8rem;
    border: none;
    outline: none;
    cursor: pointer;
    font-size: 1rem;
    border-radius: 1.5rem;


    -webkit-box-shadow: 1px 2px 5px 0px rgba(0,0,0,0.75);
    -moz-box-shadow: 1px 2px 5px 0px rgba(0,0,0,0.75);
    box-shadow: 1px 2px 5px 0px rgba(0,0,0,0.75);
}

We also need a state to control the display of the card. We would use the useState hook for our state management. The useState hook enables us to create a state variable and the function to manage the the state variable. Firstly we import the useState hook, and we define the state variable and a function to manage/change its value.

import React, { useState } from 'react';
import Modal from './components/modal/Modal';

function App() {
  const [show, setShow] = useState(false)

In the code snippet above, I defined a state variable called show and a function to change its value called setShow. We initialized the show state by passing a default value of false(Our show state would be using boolean values to toggle the display of the modal card). Check out the useState hook documentation.

We add the onclick attribute to the button and set it the the setShow function and pass the value true into the function.

<div>
      <button onClick={()=>setShow(true)} className="btn-openModal">Open Modal</button>
      <Modal />
 </div>

The button above is for making the modal card visible. We need to handle the closing of the modal. Therefore, inside the App component, we create a function called closeModalHandler. This function closes the modal by setting the show state to false.

import React, { useState } from 'react';
import Modal from './components/modal/Modal';

function App() {
  const [show, setShow] = useState(false)
  const closeModalHandler = () => setShow(false);

We pass the show state variable and the closeModalHandler into the Modal component as props. See the full code of the App Component below after passing the props.

import React, { useState } from 'react';
import Modal from './components/modal/Modal';

function App() {
  const [show, setShow] = useState(false)
  const closeModalHandler = () => setShow(false);

  return (
    <div>
      <button onClick={()=>setShow(true)} className="btn-openModal">Open Modal</button>
      <Modal show={show} closeModalHandler={closeModalHandler}/>
    </div>
  );
}

export default App;

Let us go into the Modal component to finish up the code. We first destructure the props - show and closeModalHandler - in the parameter field of the component.

function Modal({show,closeModalHandler}) {

Inside the div with class "modal-container", just before the div with class "modal-wrapper", we add a div with class "back-drop". This is the backdrop div(Remember we created a styling for this?). But we have to add this div within a ternary operator, because we want it (the backdrop div) visible only when the modal card is visible. We achieve this by using the show state(a boolean state) as the control statement. We also need to add onclick attribute into this div because we want to close the modal when the backdrop is clicked.

return (
        <div class="modal-container">
            {show ? <div onClick={closeModalHandler} className="back-drop"></div> : null}
            <div className="modal-wrapper"

Now, let us make the modal card invisible and only visible when clicked. We do this by adding an inline style to the div with class "modal-wrapper". We use opacity property to toggle the visibility, and transform property to place the card in front of the backdrop. Using the ternary operator and the show variable, we set the values of these styles.

<div className="modal-wrapper"
                style={{
                    transform:show?'translateX(0)':'translateX(0)',
                    opacity:show?'1':'0'
            }}
            >

To make the buttons in the card functional, we pass the onclick attribute and set it to the closeModalHandler(passed in as props). We do this both in the span with class "close-modal-button" and button with class "btn-cancel". See the full code of the modal component below.

import React from 'react'
import './Modal.css'

const Modal = ({show,closeModalHandler}) => {
    return (
        <div className="modal-container">
            {show ? <div onClick={closeModalHandler} className="back-drop"></div> : null}
            <div className="modal-wrapper"
                style={{
                    transform:show?'translateX(0)':'translateX(0)',
                    opacity:show?'1':'0'
            }}
            >

                <div className="modal-header">
                    <p>Glad You Are Here</p>
                    <span  onClick={closeModalHandler} className="close-modal-btn">x</span>
                </div>

                <div className="modal-content">
                    <div className="modal-body">
                    <h4>Modal</h4>
                    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Impedit tempora labore fuga officiis. Odio sed esse porro corporis pariatur cumque.</p>
                    </div>

                    <div className="modal-footer">
                        <button onClick={closeModalHandler} className="btn-cancel">Close</button>
                    </div>
                </div>                   
            </div>
        </div>
    )
}

export default Modal

We now have a fully functional and basic Modal. Please note that the styling can be changed and the components of the modal card(e.g, it can be a form for login) can be different. You can find the code full code of the project on github at bankymono/modal-type-1.