DEV Community

Cover image for HOW TO BUILD A REUSABLE AND RESPONSIVE MODAL IN REACT FROM SCRATCH
korey 🇳🇬
korey 🇳🇬

Posted on

HOW TO BUILD A REUSABLE AND RESPONSIVE MODAL IN REACT FROM SCRATCH

Source code to this tutorial is found here

Custom modal in react

A custom modal was implemented on this repo. Its quite easy with only few lines of code.

Available Scripts

In the project directory, you can run:

npm start to start the project

Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.

The page will reload if you make edits.
You will also see any lint errors in the console.

Tutorial on Dev.to

this project was bootstrapped using create react App




Building a modal in react is challenging, most especially for beginners.

The question to ask is why would we want to implement a modal component from scratch instead of relying on the existing react modal component library?

  1. It helps to understand how the modal component works under the hood.

  2. External components tend to increase the overall project size, Building your reusable component ensures you have only what you need in your project i.e. not handling other scenarios that might come with an existing pre-built component which you might not need.

Implementing the Modal component

we create a modal.js file and add the following first

import React from 'react';
import './modal.css';

const Modal = (props) => {
  const { closeModal } = props;
  return (
    <div className="overlay">
      <div className="content">
        { closeicon() }
        {props.children}
      </div>
    </div>
  );
};

export default Modal;

Enter fullscreen mode Exit fullscreen mode

the above is almost all we need to implement the modal component, what I did was to make the content of our modal (div styled as a content) a child of its parent container (div styled as an overlay).

Also, note the children of the modal component would be rendered inside the content div.

Implementing the close icon function:

For the sake of this tutorial I used react font awesome icon.

npm i react-fontawesome

   const closeicon = () => (
    <FontAwesome
    name="times"
    onClick={closeModal}
    style={{
      color: '#000000',
      padding: '10px',
      cursor: 'pointer',
      backgroundColor: 'transparent',
      border: 0,
      position: 'absolute',
      top: '0.3rem',
      right: '0.5rem',
    }}
    />
  );

Enter fullscreen mode Exit fullscreen mode

what I did from above is to create a function that returns a font-awesome icon. I added its onClick property. the value of the onClick property must be passed as props into the modal component.

The for the font awesome icon to be displayed add the following cdn to your public/index.html file

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

Note: you can always choose to use an icon within your project and apply the above styling I used for my font-awesome icon and onClick property.

The whole component so far

import React from 'react';
import './modal.css';
import FontAwesome from 'react-fontawesome';

const Modal = (props) => {
  const { closeModal } = props;

  const closeicon = () => (
    <FontAwesome
    name="times"
    onClick={closeModal}
    style={{
      color: '#000000',
      padding: '10px',
      cursor: 'pointer',
      backgroundColor: 'transparent',
      border: 0,
      position: 'absolute',
      top: '0.3rem',
      right: '0.5rem',
    }}
    />
  );

  return (
    <div className="overlay">
      <div className="content">
        { closeicon() }
        {props.children}
      </div>
    </div>
  );
};


export default Modal;

Enter fullscreen mode Exit fullscreen mode

From the above, we can see that closeModal function was passed as props to the modal component.

.overlay {
    position: fixed;
    display: block; 
    overflow: auto; 
    width: 100%; 
    height: 100%; 
    top: 0; 
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0,0,0,0.5); 
    z-index: 999; 
    cursor: pointer;
  }

.content {
        margin: 15% auto;
        background-color: white;
        border-radius: 0.25rem;
        width: 50vw;
        padding: 2rem;
        position: relative;
  }

Enter fullscreen mode Exit fullscreen mode

from the CSS style above, things to note is includes:

  • The overlay position property is fixed i.e. it's positioned relative to the viewport.
  • The content has 50vw i.e. would occupy 50% width of the viewport.

These properties ensure the modal can scale up or down and be responsive.

Making use of the modal component

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

function App() {
  const [status, setStatus] = useState(false);
  return (
    <div>
         { status && (<Modal closeModal={() => setStatus(false)}> <p>The content of the modal</p></Modal>)}
        <div className="container">
        <h2>This is the page content</h2>
        <button onClick={() => setStatus(true)}>Open Modal</button>
        </div>

    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

From the above, we rendered the Modal component conditionally.
Onclick of the button it changes the status of the modal and renders the modal component.

The function to close the modal is then passed as props into the Modal component as closeModal.

FINAL OUTPUT

Alt Text

Discussion (2)

Collapse
successgilli profile image
Awaji-mitop N. Gilbert

The modal is a little shifted to the right.

Flex justify and align can sort this out.

Nice post.

Collapse
adeyemiadekore2 profile image
korey 🇳🇬 Author

Thanks, actually didn't use flex in my implementation.

margin: 15% auto; on the content

did the job.