Reputation: 87
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://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_modal2
I found a similar topic on the problem however after trying that solution in jsfiddle I still came up with no result, does anyone have any ideas?
Previous Topic: Support for Multiple Modal Single Page
https://jsfiddle.net/oa1dr3q6/
<h2>1st Modal</h2>
<!-- Trigger/Open The Modal -->
<button id="myBtn">Open Modal</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Modal Header</h2>
</div>
<div class="modal-body">
<p>Some text in the Modal Body</p>
<p>Some other text...</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
<h2>2nd Modal</h2>
<!-- Trigger/Open The Modal -->
<button id="myBtn">Open Modal</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Modal Header</h2>
</div>
<div class="modal-body">
<p>Some text in the Modal Body</p>
<p>Some other text...</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
Script:
// Get the modal
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
Upvotes: 7
Views: 88000
Reputation: 131
I know there are many answers on here, but I wanted to share what I ended up coming up with. My solution is based off of passing an id into a function that corresponds to each modal.
In the below example I use two modals, but you can use more. You just set the id in the modal
class elements and pass the same id to the button
openModal
function in the onclick
.
var modals = document.getElementsByClassName("modal");
var modalOpenBtn = document.getElementsByClassName("modalOpenBtn");
var currentModal = null;
// Function to open modal by id
function openModal(id) {
for (i = 0; i < modals.length; i++) {
if (modals[i].getAttribute('id') == id) {
currentModal = modals[i];
currentModal.style.display = "block";
break;
}
}
}
// When the user clicks the button, open modal with the same id
modalOpenBtn.onclick = function() {
let currentID = modalOpenBtn.getAttribute('id');
openModal(currentID);
}
// When the user clicks anywhere outside of the modal or the X, close
window.onclick = function(event) {
if (event.target == currentModal || event.target.getAttribute('class') == 'modalClose') {
currentModal.style.display = "none";
}
}
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
}
.modalContent {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 40%;
max-width: 450px;
}
.modalClose {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.modalClose:hover,
.modalClose:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
<!-- Two modals here, but could use more, just update ids on the modal class elements and in the buttons onclick openModal() call. -->
<button id="modalA" class="modalOpenBtn" onclick="openModal('modalA')">Modal A</button>
<div id="modalA" class="modal">
<div class="modalContent">
<span class="modalClose">×</span>
<div>
Modal A text
</div>
</div>
</div>
<button id="modalB" class="modalOpenBtn" onclick="openModal('modalB')">Modal B</button>
<div id="modalB" class="modal">
<div class="modalContent">
<span class="modalClose">×</span>
<div>
Modal B text
</div>
</div>
</div>
I have the same ids added in each openModalBtn
class elements because you could getAttribute
the id from the clicked button instead of passing it in the function.
Upvotes: 1
Reputation: 21
My proposal
const btns = document.getElementsByClassName('btn');
const spans = document.getElementsByClassName('close');
const modals = document.getElementsByClassName('modal');
[...btns].forEach((btn, ind) => {
btn.onclick = () => (modals[ind].style.display = 'block');
});
[...spans].forEach((span, ind) => {
span.onclick = () => (modals[ind].style.display = 'none');
});
window.onclick = (e) => {
[...modals].forEach((modal) => {
if (e.target === modal) {
modal.style.display = 'none';
}
});
};
If your will not use ID but just classnames instead of
<button id="myBtn">Open Modal</button>
<div id="myModal" class="modal">
<span class="close">×</span>
just use
<button class="btn">Open Modal</button>
<div class="modal">
<span class="close">x</span>
You can store all opening buttons within HTML collection
const btns = document.getElementsByClassName('btn');
Transfer HTML collection to an array
[...btns]
Add onclick event to each button within array
.forEach((btn, ind) => {
btn.onclick = () => (modals[ind].style.display = 'block');
});
You do the same thing for span (closing button)
Upvotes: 2
Reputation: 53
Some improvements based on @junkfoodjunkie's answer
Popup / modal in html and CSS without JS :
.button {
display: inline-block;
border: 1px solid;
border-color: #012766;
background: #012766;
padding: 10px 16px;
border-radius: 4px;
color: #ffffff;
}
[id^=modal] {
display: none;
position: fixed;
top: 0;
left: 0;
}
[id^=modal]:target {
display: block;
}
input[type=checkbox] {
position: absolute;
clip: rect(0 0 0 0);
}
.popup {
width: 100%;
height: 100%;
z-index: 99999;
}
.popup__overlay {
position: fixed;
z-index: 1;
display: block;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: #000000b3;
}
.popup__wrapper {
position: fixed;
z-index: 9;
width: 80%;
max-width: 1200px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 8px;
padding: 58px 32px 32px 32px;
background: #fff;
}
.popup__close {
position: absolute;
top: 16px;
right: 26px;
}
<a class="button" href="#modal1">Open modal 1</a>
<div class="popup" id="modal1">
<a class="popup__overlay" href="#"></a>
<div class="popup__wrapper">
<a class="popup__close" href="#">Close icon here</a>
<p>POPUP 1 : CONTENT HERE</p>
</div>
</div>
<a class="button" href="#modal2">Open modal 2</a>
<div class="popup" id="modal2">
<a class="popup__overlay" href="#"></a>
<div class="popup__wrapper">
<a class="popup__close" href="#">Close icon here</a>
<p>POPUP 2 : CONTENT HERE</p>
</div>
</div>
Upvotes: 4
Reputation: 1752
On your JSFiddle, make sure you use class="myBtn"
instead of id="myBtn"
then it should work.
Here is the full working code:
HTML:
<h2>1st Modal</h2>
<!-- Trigger/Open The Modal -->
<button class="myBtn">Open Modal</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Modal Header</h2>
</div>
<div class="modal-body">
<p>Some text in the Modal Body</p>
<p>Some other text...</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
<h2>2nd Modal</h2>
<!-- Trigger/Open The Modal -->
<button class="myBtn">Open Modal</button>
<!-- The Modal -->
<div id="myModal2" class="modal">
<!-- Modal content -->
<div class="modal2-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Modal Header</h2>
</div>
<div class="modal-body">
<p>Some text in the Modal Body</p>
<p>Some other text...</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
JS:
// Get the modal
var modal = document.getElementsByClassName('modal');
// Get the button that opens the modal
var btn = document.getElementsByClassName("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close");
// When the user clicks the button, open the modal
btn[0].onclick = function() {
modal[0].style.display = "block";
}
btn[1].onclick = function() {
modal[1].style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span[0].onclick = function() {
modal[0].style.display = "none";
}
span[1].onclick = function() {
modal[1].style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal[0]) {
modal[0].style.display = "none";
}
if (event.target == modal[1]) {
modal[1].style.display = "none";
}
}
Upvotes: 1
Reputation: 390
I Know i'm late.
Check this out.
body {
font-family: Arial, Helvetica, sans-serif;
}
/* The Modal (background) */
.modal {
display: none;
/* Hidden by default */
position: fixed;
/* Stay in place */
z-index: 1;
/* Sit on top */
padding-top: 80px;
/* Location of the box */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: rgb(0, 0, 0);
/* Fallback color */
background-color: rgba(0, 0, 0, 0.4);
/* Black w/ opacity */
overflow: auto;
}
/* Modal Content */
.modal-content {
max-height: 80%;
overflow: auto;
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
border: 1px solid #888;
width: 80%;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: animatetop;
animation-duration: 0.4s
}
/* Add Animation */
@-webkit-keyframes animatetop {
from {
top: -300px;
opacity: 0
}
to {
top: 0;
opacity: 1
}
}
@keyframes animatetop {
from {
top: -300px;
opacity: 0
}
to {
top: 0;
opacity: 1
}
}
/* The Close Button */
.close {
color: white;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.modal-header {
padding: 2px 16px;
background-color: #5cb85c;
color: white;
}
.modal-body {
padding: 2px 16px;
}
.modal-footer {
padding: 2px 16px;
background-color: #5cb85c;
color: white;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="modal.css">
</head>
<body>
<button id="myBtn">Button 1</button>
<button id="myBtn1">Button 2</button>
<button id="myBtn2">Button 3</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Button 1 Clicked</h2>
</div>
<div class="modal-body">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus aspernatur perferendis ad sunt.
Eius, possimus? Quae at eum repudiandae obcaecati vitae accusantium, perferendis sapiente
temporibus, necessitatibus voluptatem iste cumque et?</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
<!-- The Modal -->
<div id="myModal1" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Button 2 Clicked</h2>
</div>
<div class="modal-body">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores voluptatum ipsa cum aliquid, ex
inventore, culpa obcaecati modi deleniti enim consequuntur tenetur. Earum numquam sit ratione eum
sequi praesentium, unde maxime ullam iure rem mollitia perferendis eos possimus neque, nisi dicta.
Obcaecati dignissimos, dolores labore rerum quisquam non explicabo repellat!</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
<!-- The Modal -->
<div id="myModal2" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Button 3 Clicked</h2>
</div>
<div class="modal-body">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit laudantium quia non laborum
ea, similique ex iusto minus obcaecati optio sapiente aut eveniet porro odio veniam excepturi
facilis iste fuga? Porro atque odio, fuga blanditiis voluptate ducimus veritatis id ea possimus?
Facilis tempore officiis quos assumenda dolorem placeat sed veniam dolor eveniet magnam. Iure ullam
odit qui, magni suscipit pariatur nesciunt temporibus aspernatur doloribus quis nobis quas esse
perspiciatis, asperiores eum quidem placeat minus alias veniam molestias sit. Ipsam numquam,
sapiente facere voluptatem eum, maiores blanditiis cupiditate corporis quos ratione, quia
praesentium dolore nihil voluptatum impedit quae consequatur sit pariatur.
</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
<script>
var datamap = new Map([
[document.getElementById("myBtn"), document.getElementById("myModal")],
[document.getElementById("myBtn1"), document.getElementById("myModal1")],
[document.getElementById("myBtn2"), document.getElementById("myModal2")]
]);
datamap.forEach((value, key) => {
doModal(key, value);
});
function doModal(anchor, popupbox) {
// Get the <span> element that closes the modal
var span = popupbox.getElementsByClassName("close")[0];
anchor.addEventListener("click", function (event) {
popupbox.style.display = "block";
});
span.addEventListener("click", function (event) {
popupbox.style.display = "none";
});
window.addEventListener("click", function (event) {
if (event.target == popupbox) {
popupbox.style.display = "none";
}
});
}
</script>
</body>
</html>
Just keep adding the entry in MAP for every popup you create. in Map
1st Parameter Element which is used to display popup. (in out case it's buttons)
2nd Parameter Modal Popup window itself
Upvotes: 2
Reputation: 1069
An update on the excellent answer given by Denis Mysenko:
My JS used to be (for one modal):
let modal = document.getElementById('about-modal');
let btn = document.getElementById('about-modal-btn');
let close = document.getElementsByClassName('close')[0];
btn.onclick = function() {
modal.style.display = 'block';
}
close.onclick = function() {
modal.style.display = 'none';
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = 'none';
}
}
window.onkeydown = function(event) {
if (event.key == 'Escape') {
modal.style.display = 'none';
}
}
My new JS (adopted from Denis's answer:
let modals = document.getElementsByClassName('modal');
let modalBtns = document.getElementsByClassName('modal-btn');
let closeBtns = document.getElementsByClassName('close');
for(let modalBtn of modalBtns) {
modalBtn.onclick = function(event) {
document.querySelector(event.target.getAttribute('href') ).style.display = 'block';
}
}
for(let closeBtn of closeBtns) {
closeBtn.onclick = function(event) {
event.target.parentNode.parentNode.style.display = 'none';
}
}
window.onclick = function(event) {
if(event.target.classList.contains('modal') ) {
for(let modal of modals) {
if(typeof modal.style !== 'undefined') {
modal.style.display = 'none';
}
}
}
}
window.onkeydown = function(event) {
if (event.key == 'Escape') {
for(let modal of modals) {
modal.style.display = 'none';
}
}
}
Hopefully this helps someone else in the future. I cleaned up some inconsistencies and other minor things and simplified the code and variable names, using es6 syntax, etc. Someone can also probably make use of the code for a single modal. Sample modal structure:
<button id="settings-modal-btn" class="modal-btn" href="#settings-modal">Settings</button>
<div id="settings-modal" class="modal">
<div class="modal-content">
<button class="close">×</button>
<p>Content here...</p>
</div>
</div>
Upvotes: 0
Reputation: 6534
You assigned the same Id to both modal triggering buttons. Different elements shouldn't have the same Id.
In you JavaScript code, you always pick a single element (a single close button, a single open button, etc).
It's a HTML/JS beginner's mistake I would say. This would work:
// Get the button that opens the modal
var btn = document.querySelectorAll("button.modal-button");
// All page modals
var modals = document.querySelectorAll('.modal');
// Get the <span> element that closes the modal
var spans = document.getElementsByClassName("close");
// When the user clicks the button, open the modal
for (var i = 0; i < btn.length; i++) {
btn[i].onclick = function(e) {
e.preventDefault();
modal = document.querySelector(e.target.getAttribute("href"));
modal.style.display = "block";
}
}
// When the user clicks on <span> (x), close the modal
for (var i = 0; i < spans.length; i++) {
spans[i].onclick = function() {
for (var index in modals) {
if (typeof modals[index].style !== 'undefined') modals[index].style.display = "none";
}
}
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target.classList.contains('modal')) {
for (var index in modals) {
if (typeof modals[index].style !== 'undefined') modals[index].style.display = "none";
}
}
}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
border: 1px solid #888;
width: 80%;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: animatetop;
animation-duration: 0.4s
}
/* Add Animation */
@-webkit-keyframes animatetop {
from {top:-300px; opacity:0}
to {top:0; opacity:1}
}
@keyframes animatetop {
from {top:-300px; opacity:0}
to {top:0; opacity:1}
}
/* The Close Button */
.close {
color: white;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.modal-header {
padding: 2px 16px;
background-color: #5cb85c;
color: white;
}
.modal-body {padding: 2px 16px;}
.modal-footer {
padding: 2px 16px;
background-color: #5cb85c;
color: white;
}
<h2>1st Modal</h2>
<!-- Trigger/Open The Modal -->
<button class="modal-button" href="#myModal1">Open Modal</button>
<!-- The Modal -->
<div id="myModal1" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Modal Header</h2>
</div>
<div class="modal-body">
<p>Some text in the Modal Body</p>
<p>Some other text...</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
<h2>2nd Modal</h2>
<!-- Trigger/Open The Modal -->
<button class="modal-button" href="#myModal2">Open Modal</button>
<!-- The Modal -->
<div id="myModal2" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Modal Header</h2>
</div>
<div class="modal-body">
<p>Some text in the Modal Body</p>
<p>Some other text...</p>
</div>
<div class="modal-footer">
<h3>Modal Footer</h3>
</div>
</div>
</div>
Upvotes: 12
Reputation: 3178
Why are you using so much code, and javascript to do something you can do using just CSS and HTML? (simplified example, animations and such can of course be added)
[id^=modal] {
display: none;
border: 1px solid red;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
min-height: 3em;
min-width: 5em;
max-width: 10em;
}
input[type=checkbox] {
position: absolute;
clip: rect(0 0 0 0);
}
#modal1:target {
display: block;
}
#modal2:target {
display: block;
}
[id^=modal] a {
float: right;
}
<div id="content">
<p>This is the content-container</p>
<a href="#modal1">Open first modal</a><br>
<a href="#modal2">Open second modal</a>
<div id="modal1"><a href="#">Close</a>This is the first modal</div>
<div id="modal2"><a href="#">Close</a>This is the second modal</div>
</div>
Upvotes: 2