I\'m having some issues creating multiple modals on a single webpage following the sample code from w3schools.com. The code in question that I am using is this one: http://w
Update September 2020: The code in my answer is a slightly outdated version of the one in my blog post. Please view the post itself for the most recent version, along with explanations.
I know I'm necroing a dead post here, but I'd like to propose a cleaner, more maintainable solution. I wrote an in-depth guide on how to create multiple modals on a single page on my blog. The explanations are a bit involved, so if you want to understand how this code works, I break things down in detail in that post.
Two versions of the code are below, depending on what you want to accomplish: multiple stacked modals or multiple side-by-side modals.
I hope this helps anyone who comes across this in the future.
Creating stacked modals
// Stack of modals
let currentlyOpenModals = [];
const noModalsOpen = () => !currentlyOpenModals.length;
const openModal = modalId => {
const modalWrapper = document.getElementById(modalId);
modalWrapper.classList.add("visible");
currentlyOpenModals.push(modalWrapper);
};
// By definition, it's always the topmost modal that will be closed first
const closeTopmostModal = () => {
if (noModalsOpen()) {
return;
}
const modalWrapper = currentlyOpenModals[currentlyOpenModals.length - 1];
modalWrapper.classList.remove("visible");
currentlyOpenModals.pop();
};
const modalTriggers = document.querySelectorAll(".modal-trigger");
modalTriggers.forEach(modalTrigger => {
modalTrigger.addEventListener("click", clickEvent => {
const trigger = clickEvent.target;
const modalId = trigger.getAttribute("data-modal-id");
openModal(modalId);
});
});
// Otherwise, clicking the content of a modal will propagate the click to the modal wrapper,
// and that will close the entire thing. That's not what we want!
document.querySelectorAll(".modal-window").forEach(modal => {
modal.addEventListener("click", clickEvent => {
clickEvent.stopPropagation();
});
});
const modalWrappers = document.querySelectorAll(".modal-wrapper");
modalWrappers.forEach(modalWrapper => {
modalWrapper.addEventListener("click", () => {
closeTopmostModal();
});
});
document.querySelectorAll(".close-modal-button").forEach(closeModalButton => {
closeModalButton.addEventListener("click", () => {
closeTopmostModal();
});
});
document.body.addEventListener("keyup", keyEvent => {
if (keyEvent.key === "Escape") {
closeTopmostModal();
}
});
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
align-items: center;
display: flex;
flex-direction: column;
font-family: Arial;
font-size: 18px;
height: 100vh;
justify-content: center;
}
p {
margin-bottom: 1em;
}
.modal-wrapper {
align-items: center;
background-color: rgba(100, 100, 100, 0.5);
bottom: 0;
display: flex;
flex-wrap: wrap;
height: 100vh;
justify-content: center;
left: 0;
opacity: 0;
position: fixed;
right: 0;
transition: all 0.2s ease-in-out;
visibility: hidden;
width: 100%;
z-index: 1000;
}
.modal-wrapper.visible {
opacity: 1;
visibility: visible;
}
.modal-window {
background-color: white;
border-radius: 5px;
box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
padding: 20px;
transform: scale(0);
transition: 0.2s ease-in-out all;
}
.modal-wrapper.visible .modal-window {
transform: scale(1);
}
.modal-header {
align-items: center;
border-bottom: 2px solid black;
display: flex;
justify-content: space-between;
margin-bottom: 20px;
padding-bottom: 20px;
}
.close-modal-button {
align-items: center;
cursor: pointer;
display: flex;
height: 30px;
justify-content: center;
width: 30px;
}
.close-modal-button::before {
content: "X";
color: rgb(112, 112, 112);
}
.close-modal-button:hover::before {
color: black;
}
.modal-trigger, a {
color: rgb(10, 47, 255);
cursor: pointer;
text-decoration: underline;
}
Stacked Modals Demo
Lorem ipsum. Click this trigger to open a modal.
Close a modal by clicking off to the side, clicking the X, or pressing Escape.
Title goes here...
Congrats, you've opened a modal!
Now open another modal!
Modalception