In this article, we will see how to create a modal in React and close it when clicked outside.
Project setup
First, create a react app using the following command:
npx create-react-app react-modal
Now update the index.css
with the following styles. These are some styles that will be used to style and align the modal:
body {
display: flex;
justify-content: center;
}
.modal {
position: fixed;
background-color: rgba(0, 0, 0, 0.5);
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
}
.modal-content {
background-color: white;
width: 600px;
border-radius: 5px;
}
.modal-title {
padding: 0.8rem;
font-size: 1.5rem;
border-bottom: 1px solid #aaa;
text-align: center;
}
.modal-body {
padding: 1rem;
}
.modal-footer {
border-top: 1px solid #aaa;
padding: 0.8rem;
display: flex;
justify-content: flex-end;
}
.modal-footer button {
cursor: pointer;
}
In the index.html
file, which can be found inside the public
directory, add a div with id modal-root
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="modal-root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Now create a component called Modal.js
with the following code:
import React, { useEffect } from "react"
import ReactDOM from "react-dom"
const Modal = ({ onClose }) => {
useEffect(() => {
document.body.style.overflow = "hidden"
return () => {
document.body.style.overflow = "auto"
}
}, [])
return ReactDOM.createPortal(
<div className="modal">
<div className="modal-content">
<div className="modal-title">Modal Title</div>
<div className="modal-body">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quaerat,
sint ab ex odio pariatur et eius? Nam, quod eum adipisci earum nisi
tempora, nesciunt esse voluptate illo, maxime consectetur harum!
</div>
<div className="modal-footer">
<button onClick={onClose}>Close</button>
</div>
</div>
</div>,
document.getElementById("modal-root")
)
}
export default Modal
Here we are creating a react portal and mounting it to the div with the id modal-root
, created earlier.
We need to create the modal in a separate div outside the root div so that we can render the modal on top of the existing content.
Here we have a useEffect hook, which is used to hide the scrollbar when the modal is open so that the scrolling is blocked when the modal is open.
Now in App.js
, create enough content to induce a scrollbar and add a button, when clicked will open the modal.
import { useState } from "react"
import Modal from "./Modal"
function App() {
const [isModalOpen, setIsModalOpen] = useState(false)
return (
<div>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Distinctio
vero facere necessitatibus ipsum, veritatis autem natus eius, fugiat hic
eligendi dignissimos voluptatum. Recusandae corrupti dolorem consectetur
sequi excepturi inventore facilis! Consequatur non ullam magni fugiat
natus expedita saepe voluptatem impedit est odio! Sint consequatur aut
maiores illum. Libero eos sapiente adipisci aliquid nisi magnam ad qui
minus voluptate, id et? Unde eum ea excepturi expedita ipsa debitis
corrupti? Ex voluptatem assumenda velit consectetur! Rerum, rem
laudantium accusantium vitae vero ipsa delectus corporis quibusdam
nihil, explicabo aliquam necessitatibus dignissimos sint labore. Optio
itaque quo earum iusto, ipsum eius culpa consequatur, nihil, tempore
inventore a dolor eos deserunt vitae sit aliquam? Molestiae quia
inventore omnis pariatur consectetur sit sed, labore mollitia quis!
Voluptatem consequatur sit corporis itaque, repudiandae temporibus id
sint similique qui? Odio minus nam quia dignissimos fuga consectetur
commodi minima adipisci nulla eius optio sunt explicabo quidem, vero
tenetur voluptatibus? Ex possimus iste necessitatibus vero commodi natus
iure tempore dicta neque laudantium, libero ullam odit quibusdam nobis
voluptate molestiae. Mollitia facere iusto maiores eius quisquam ab
architecto voluptatum veniam exercitationem. Suscipit magnam veritatis
enim? Qui excepturi nemo aperiam numquam libero assumenda recusandae
quos dignissimos possimus mollitia non deleniti aut expedita soluta
nobis eaque, tempora laboriosam animi consectetur nam sit veniam?
Voluptatem temporibus, saepe quos eum enim ipsum accusamus qui? Odio
quidem magni reprehenderit dolores saepe nemo tenetur eaque labore
assumenda. Explicabo placeat non mollitia a quos, dolor laborum suscipit
quaerat! Recusandae, nemo adipisci nihil ipsum vero quia accusantium
non? Eligendi in ex quo sint repellat ab, nemo delectus. Consequuntur
non officia eos temporibus quis odit dolor ratione praesentium quae ex.
Iste vel necessitatibus, facilis, minima nihil ullam obcaecati non ipsam
tenetur dicta fugit explicabo accusantium rerum autem? Dolores vero quia
nam animi quis, non deserunt officiis quasi natus ipsa accusamus.
Dolores optio saepe dignissimos fugiat autem aliquid perspiciatis,
consequuntur provident? Dignissimos eligendi facilis vero eaque,
consequatur tempore, labore aperiam, cupiditate dolores praesentium
amet? Eius nemo quisquam animi enim blanditiis doloremque? Inventore
quisquam officiis itaque animi culpa suscipit, iusto obcaecati sapiente,
facere architecto tenetur, laudantium repellendus quis nisi! Voluptatem
adipisci fugit facere libero consequuntur magni consequatur, totam
magnam necessitatibus minima illum? Possimus a commodi labore architecto
autem dicta officiis harum vitae quos repellendus, nesciunt
exercitationem amet, expedita libero explicabo, dolores sapiente
laudantium modi? Excepturi explicabo debitis neque optio corporis non
atque. Dolorem aliquid sed, quasi officia dolores temporibus rem nulla
eligendi fugit consectetur praesentium, iusto quam! Ipsam voluptatum
assumenda facere, saepe, iste maiores placeat, earum quos neque at
deleniti omnis eos. Ipsam sequi provident quis qui mollitia doloribus
magnam recusandae et ratione earum dolore fugit itaque, laborum eligendi
similique inventore. Incidunt quo officia et ea minus soluta voluptas
est illum minima! Libero, voluptate. Illum praesentium in suscipit
numquam necessitatibus beatae quaerat officia architecto.
</p>
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
{isModalOpen && <Modal onClose={() => setIsModalOpen(false)} />}
<p>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Illum iure id
repudiandae, aspernatur ea ut corporis provident explicabo minus odit
commodi, labore optio unde delectus tenetur vitae necessitatibus. Ullam,
illo. Maxime doloremque rerum eius quae aspernatur accusantium tempore
nobis, sapiente officia, non necessitatibus aperiam omnis assumenda
quisquam cum esse eligendi nemo laudantium nihil labore aliquid modi
vel! Quos, quo tempora! Dolore libero quos alias ipsum unde dolor nisi
sed perferendis laborum non sunt corporis a quam aliquam, eveniet
doloribus laboriosam sequi cupiditate deleniti, molestiae recusandae, ut
labore minima! Vero, eos. Reiciendis nostrum itaque placeat perferendis
doloremque earum cupiditate nihil voluptatibus officia excepturi odio
ipsam molestias similique quibusdam, doloribus minus culpa. Provident
similique dolor assumenda magnam eveniet, vitae aspernatur recusandae
nesciunt. Culpa sint minus sunt iste distinctio ipsa perferendis debitis
nostrum provident? Neque totam doloribus obcaecati, accusantium aliquid
suscipit nobis alias illo nostrum eius harum quasi explicabo voluptatem
architecto molestiae veritatis. Quis quibusdam eius perferendis odio
illum et unde! Repellat facilis autem earum quidem voluptatem. Itaque
cumque ipsum nostrum libero corrupti sequi temporibus voluptas commodi
quia, molestiae a unde eveniet aperiam. Commodi veniam aspernatur nam
quas blanditiis tempore harum hic? Perspiciatis, excepturi! Ratione ex
vero reiciendis cum eos est vitae eius dignissimos quo necessitatibus
aut fugit amet dicta, deserunt ad libero. Animi incidunt dolorem magnam
natus qui rem inventore impedit, accusamus ratione, consequatur
repellendus harum error autem nemo quos repudiandae itaque, amet beatae.
Aut, fugit ea necessitatibus odio veniam illo sit? Explicabo quasi fuga
non sed magni corporis tenetur delectus dolore! Praesentium rerum facere
illo delectus harum commodi porro repudiandae quas! Sint eligendi
dolore, minima nostrum facilis dolorum quisquam dolores amet? Vitae
incidunt, corrupti dolorum, voluptatem mollitia aspernatur perspiciatis
dicta repudiandae ut eligendi id et vero. Consectetur illum ipsum unde!
Iste porro ab nobis officiis, vero debitis consectetur ipsa error
reprehenderit? Nulla eaque unde saepe inventore quas? Mollitia
aspernatur eum expedita! Ipsa quia maxime repellendus non nisi.
Accusamus, doloremque. Obcaecati quisquam voluptates natus reprehenderit
ratione cupiditate iusto tenetur soluta doloremque. Facilis. Quo id
illum voluptatibus quod ducimus error similique ut facere, quas iusto
eius eveniet consectetur deserunt magnam natus ex. Culpa beatae
voluptatem sit inventore odit voluptate reprehenderit fuga, qui
mollitia! Doloribus rerum ipsam atque, laudantium impedit consequatur
doloremque corrupti optio laboriosam incidunt unde sint, aliquam velit
dolor quod autem, quisquam maxime est provident porro culpa? Corporis
voluptas aut suscipit nesciunt. Sed itaque nihil, sit eaque amet odit
libero necessitatibus illo blanditiis ut tempora explicabo. Eius odio
ducimus hic voluptates, voluptatibus culpa velit consequuntur tempora
quaerat aliquid quas. Explicabo, soluta voluptatibus. Quod dolorem eaque
consequatur neque ipsa laborum fuga minus? Atque culpa cupiditate,
aperiam quod soluta voluptatum sint sit iure minus asperiores rerum.
Minima officia animi, molestiae dolorem autem reprehenderit a? Porro
excepturi, corporis nihil et rerum recusandae minus impedit quaerat
sapiente ducimus earum ipsa aspernatur vero magnam maiores quae facilis
laudantium? Illum ipsam aperiam sunt voluptatum. Delectus explicabo
laborum maxime! Reprehenderit maxime dignissimos cumque tenetur
necessitatibus maiores molestiae quisquam ipsum explicabo. Consequuntur
ad sapiente reprehenderit, ipsum et exercitationem quod dolore!
Consectetur nihil earum aliquam aspernatur, excepturi consequuntur
tempore libero autem. Vitae enim nihil ut? Veniam consequatur explicabo
fuga commodi assumenda? Laborum cum non voluptatibus error accusantium
fugit, deleniti iusto et. Quidem culpa minima fuga unde, deserunt facere
modi dolorem voluptatibus? Delectus, fugit ducimus magnam non ut quos
aspernatur iste impedit qui, dignissimos excepturi eos corrupti
voluptatum, repellendus ipsam deleniti suscipit harum repellat
voluptates dolorem. Alias id fuga laboriosam eligendi quibusdam? Libero
ullam pariatur incidunt optio a voluptas, iusto laboriosam cumque quas
architecto numquam tempora inventore maiores dignissimos explicabo
suscipit distinctio vero provident. Fugit nobis reiciendis
exercitationem soluta dicta dolorum consequuntur. Consequatur itaque
maxime quaerat. Aut rem praesentium deleniti dolor odio nisi, dolores at
eveniet cupiditate expedita maiores optio veritatis esse impedit beatae
commodi nostrum quam delectus explicabo laboriosam asperiores molestiae!
Omnis culpa iste illo perferendis vitae reprehenderit facere, voluptate
aspernatur accusantium ad sit, animi velit ex dolor eos, laborum
molestias? A porro maiores, nostrum laborum non mollitia unde aspernatur
quo. Voluptatibus maxime quis blanditiis vitae cupiditate quo vel
voluptates consectetur sequi commodi dolorem, rerum, maiores officiis
nobis expedita! Ducimus nostrum vitae omnis ad rerum atque animi ipsum!
Quisquam, doloribus autem! Aut sapiente explicabo maiores dolores
commodi tempore eligendi quibusdam distinctio ducimus, consequuntur in
enim nobis rerum mollitia aspernatur odio deserunt officia veniam beatae
officiis. Quibusdam tempore numquam dolore officia ad? Consequatur
repellat hic atque commodi amet error unde voluptates mollitia illum
placeat eaque maiores dolorem corrupti, quae provident magnam incidunt
earum. Libero praesentium ipsa voluptates, in architecto corporis
aliquid nostrum. Veniam aperiam perspiciatis aliquam placeat, excepturi
recusandae vel ex! Mollitia fugit blanditiis vel! Quaerat voluptas illum
non laboriosam quia voluptatem amet tenetur debitis nobis totam! Sint
perferendis velit maiores fugiat. Voluptatum at praesentium doloremque
amet illum magni provident tenetur earum qui harum ex voluptatibus
aliquid, nemo culpa. Totam corrupti, quas, quos nesciunt facere eius
delectus optio recusandae voluptatibus debitis quasi. Quasi,
voluptatibus consectetur ipsum accusantium molestiae est voluptatum
aperiam? Delectus architecto, culpa et labore repudiandae minus
quibusdam autem inventore adipisci eligendi laborum obcaecati quasi
maxime! Molestiae minima laborum maiores laudantium. Facere inventore
eligendi quibusdam corporis nulla ab dolore, ipsam et ea consectetur est
aliquam rem deserunt culpa deleniti cumque unde exercitationem
laudantium labore? Nulla, tenetur ducimus delectus quia totam amet. Quia
neque sed ad incidunt, voluptas veniam voluptatum mollitia soluta
doloribus temporibus qui debitis eveniet sequi aut ullam impedit
voluptates molestias ipsa alias vitae illum. Ex nostrum obcaecati sequi
odio. Consequuntur laborum odit ut voluptatibus adipisci officiis,
aperiam recusandae enim atque commodi dignissimos error magni sunt
libero illo! Iusto rerum pariatur nisi quaerat, repellendus soluta vitae
velit labore expedita officiis! Ratione totam nemo accusamus. Nemo autem
nesciunt, sequi quia eaque, est, odio esse praesentium debitis aperiam
voluptatem omnis deleniti. Omnis sequi sunt quasi modi dolore rem quam
accusamus similique voluptas. Reprehenderit eaque esse sint inventore
facere numquam soluta nemo unde, necessitatibus rerum vel quos deleniti
similique, atque perspiciatis recusandae. Numquam, illum nemo unde
necessitatibus fuga perspiciatis reprehenderit a sunt iste! Perferendis
pariatur numquam neque iure tenetur nisi maxime exercitationem inventore
tempore harum quaerat officiis magni fugit laboriosam placeat in, est
hic repudiandae molestias odio. Voluptatibus laboriosam alias temporibus
eveniet laudantium! Nesciunt doloremque exercitationem quae quas
consequatur ex suscipit odio, doloribus delectus? Consectetur culpa
earum non, inventore, iste architecto libero facere eligendi a,
explicabo sed nostrum? Rem fuga voluptas ea voluptatem. Sint, voluptate
voluptatibus! Similique voluptate et quibusdam veniam perspiciatis
deserunt impedit earum, optio consequatur voluptatum est reprehenderit
in beatae sapiente hic pariatur rem distinctio. Iure expedita ipsum
impedit minus harum. Dolore illum repellendus cupiditate quo dolor sint,
deserunt nesciunt magni corporis inventore eos quaerat vitae quas esse
minus dolorum illo suscipit soluta repudiandae, blanditiis ipsam
commodi, consequatur eaque doloremque.
</p>
</div>
)
}
export default App
In the above code, we are maintaining a local state to store if the modal is open.
If the state is true, we are displaying the modal. We are passing a callback named onClose
,
which will set the state to false so that the modal can be closed.
Now, if you run the app and click on the button, you should be able to see the modal.
Closing the modal when clicked outside
As of now, if you click outside the modal, nothing will happen.
To close the modal when the user clicks outside,
first, we need to detect if the user has clicked outside.
For that we can make use of refs:
import React, { useEffect, useRef } from "react"
import ReactDOM from "react-dom"
const Modal = ({ onClose }) => {
const ref = useRef()
useEffect(() => {
const checkIfClickedOutside = e => {
if (ref.current && !ref.current.contains(e.target)) {
onClose()
}
}
document.addEventListener("click", checkIfClickedOutside)
return () => {
document.removeEventListener("click", checkIfClickedOutside)
}
}, [onClose])
useEffect(() => {
document.body.style.overflow = "hidden"
return () => {
document.body.style.overflow = "auto"
}
}, [])
return ReactDOM.createPortal(
<div className="modal">
<div className="modal-content" ref={ref}>
<div className="modal-title">Modal Title</div>
<div className="modal-body">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quaerat,
sint ab ex odio pariatur et eius? Nam, quod eum adipisci earum nisi
tempora, nesciunt esse voluptate illo, maxime consectetur harum!
</div>
<div className="modal-footer">
<button onClick={onClose}>Close</button>
</div>
</div>
</div>,
document.getElementById("modal-root")
)
}
export default Modal
Here we have created a reference to the modal-content
div and in the useEffect we check if the div contains (is inside) the clicked target.
If that is not the case (not condition), then we close the modal.
Source code and Demo
You can view the complete source code here and a demo here.
Top comments (0)