Have a look at this react code on creating a modal:
import * as React from "react";
import "./styles.css";
function Modal({ handleClose }) {
return (
<div onClick={handleClose}>
<dialog>
<header>
<button onClick={handleClose}>X</button>
<h2>Modal</h2>
</header>
<section>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ullamcorper morbi
tincidunt ornare massa. Morbi enim nunc faucibus a pellentesque sit
amet. Duis tristique sollicitudin nibh sit amet commodo nulla facilisi
nullam. Eget dolor morbi non arcu risus. Integer eget aliquet nibh
praesent tristique magna sit amet purus. Nullam vehicula ipsum a arcu.
Vitae proin sagittis nisl rhoncus mattis rhoncus. Risus feugiat in ante
metus dictum at tempor.
</p>
</section>
</dialog>
</div>
);
}
export default function App() {
const [isOpen, setIsOpen] = React.useState(false);
return (
<div className="container">
{/* Modal */}
{isOpen && <Modal handleClose={() => setIsOpen(false)} />}
{/* Main Content */}
<main>
<header>
<h1>Test-Modal</h1>
</header>
{["red", "blue", "green", "pink", "purple", "yellow"].map(
(color, index) => {
return (
<section
key={index}
style={{
backgroundColor: color,
width: "100%",
height: "50vh",
}}
/>
);
}
)}
<button className="primary" onClick={() => setIsOpen(true)}>
openModal
</button>
</main>
</div>
);
}
styles.css
html {
background-color: black;
color: white;
}
.container {
margin: 0 auto;
max-width: 1100px;
padding: 50px;
position: relative;
}
main {
margin: auto;
padding: 24px;
}
main > header {
position: sticky;
top: 0;
background: black;
text-align: center;
padding: 24px;
}
dialog {
position: fixed;
display: grid;
grid-template-rows: auto 1fr;
top: 40px;
background: transparent;
width: 75vw;
margin: auto;
animation: expand 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
border-radius: 8px;
padding: 32px;
z-index: 10;
color: white;
}
dialog section {
max-height: calc(90vh - 120px);
overflow: auto;
}
dialog button {
position: absolute;
top: 16px;
right: 16px;
width: 32px;
height: 32px;
border-radius: 50%;
}
div:has(dialog) {
background-color: rgba(0, 0, 0, 0.5);
position: fixed;
/* width: 100%; */
/* height: 100%; */
z-index: 9;
display: flex;
align-items: center;
justify-content: center;
inset: 0;
}
.primary {
position: fixed;
bottom: 40px;
right: 40px;
}
You can run full code here.
I have a few questions:
- Why
<main>
is shinked and the contents are back to top when I open the modal? - Why can’t I scroll the contents in
main
when the modal is opened?
I have worked on this for a whole night for solutions.
If I make the modal simpler like this:
<div
style={{
backgroundColor: "rgba(0,0,0,0.5)",
zIndex: 9999,
display: "flex",
justifyContent: "center",
alignItems: "center",
inset: 0,
position: "fixed",
}}
onClick={handleClose}
>
<div style={{ backgroundColor: "white", padding: "30px" }}>
<h2 style={{ color: "black" }}>some title...</h2>
<p style={{ color: "black" }}>some content</p>
</div>
</div>;
Then everything is fine.
The bug seems to be from css.
I want to figure out what caused the bug and how to fix it, if the modal is as complex as that.
2
Answers
you can use ReactModal from "react-modal" which gives you functionality when isOpen prop is true, In other words when Modal is open.
It has function like "onAfterOpen". Read more on –
http://reactcommunity.org/react-modal/
But, for now you can use this work around. when "isSetOpen" is true, I made some changes in App.
Also made some changes in dialog element for make it more visible. Like background color, color, line-height.
The issue lies
div:has(dialog)
. You have addedflex
properties with in it which is messing layout of main content and if you remove it then issue will get resolved and according to my inspection flex properties is not serving any purpose to your layout and if it does then do share.Also instead of using
position: fixed
useposition: absolute
it is best for this usecase. Below is updated css which you need to fix the issue. If I have misunderstood or missed something then do share.