1

I'm new with JS, I'm trying to use 2 modal images on same page with this code:

https://www.w3schools.com/howto/howto_css_modal_images.asp

With this HTML, JS and CSS view resizing works only for one image, not sure how to make it work for two images on same page:

I have first html code two times for each image:

HTML:

<img id="myImg" src="img_fjords.jpg" alt="Trolltunga, Norway" width="300" height="200">
<div id="myModal" class="modal">
  <span class="close">&times;</span>
  <img class="modal-content" id="img01">
  <div id="caption"></div>
</div> 

CSS in big-picture.css:

#myImg {
    border-radius: 5px;
    cursor: pointer;
    transition: 0.3s;
}

#myImg:hover {opacity: 0.7;}

.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.9); /* Black w/ opacity */
}

.modal-content {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
}

#caption {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
    text-align: center;
    color: #ccc;
    padding: 10px 0;
    height: 150px;
}

.modal-content, #caption {
    animation-name: zoom;
    animation-duration: 0.6s;
}

@keyframes zoom {
    from {transform:scale(0)}
    to {transform:scale(1)}
}

.close {
    position: absolute;
    top: 15px;
    right: 35px;
    color: #f1f1f1;
    font-size: 40px;
    font-weight: bold;
    transition: 0.3s;
}

.close:hover,
.close:focus {
    color: #bbb;
    text-decoration: none;
    cursor: pointer;
}

@media only screen and (max-width: 700px){
    .modal-content {
        width: 100%;
    }
} 

and JS:

var modal = document.getElementById('myModal');
var img = document.getElementById('myImg');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
img.onclick = function(){
    modal.style.display = "block";
    modalImg.src = this.src;
    captionText.innerHTML = this.alt;
}

var span = document.getElementsByClassName("close")[0];

span.onclick = function() {
  modal.style.display = "none";
} 
lf80
  • 455
  • 3
  • 10
  • 22
  • Well, first, none of that code is jQuery. Change your tags. Second, in your example, you've hardcoded a reference to a single image: document.getElementById() -- so it'll only work with that one image. – Snowmonkey Dec 13 '17 at 17:36

4 Answers4

11

The code you have mostly works, but you're referencing specifically a single image. By using document.getElementById(), you haven't allowed for a second image. I've changed your code a little -- the HTML now has a few images for sample purposes and the JS now uses document.getElementsByClassName() to allow for multiple images. Further, I'm iterating over the list of images, and attaching that event handler to each one. See it as a fiddle, or here it is:

// create references to the modal...
var modal = document.getElementById('myModal');
// to all images -- note I'm using a class!
var images = document.getElementsByClassName('myImages');
// the image in the modal
var modalImg = document.getElementById("img01");
// and the caption in the modal
var captionText = document.getElementById("caption");

// Go through all of the images with our custom class
for (var i = 0; i < images.length; i++) {
  var img = images[i];
  // and attach our click listener for this image.
  img.onclick = function(evt) {
    modal.style.display = "block";
    modalImg.src = this.src;
    captionText.innerHTML = this.alt;
  }
}

var span = document.getElementsByClassName("close")[0];

span.onclick = function() {
  modal.style.display = "none";
}
#myImg {
  border-radius: 5px;
  cursor: pointer;
  transition: 0.3s;
}

#myImg:hover {
  opacity: 0.7;
}

.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.9);
  /* Black w/ opacity */
}

.modal-content {
  margin: auto;
  display: block;
  width: 80%;
  max-width: 700px;
}

#caption {
  margin: auto;
  display: block;
  width: 80%;
  max-width: 700px;
  text-align: center;
  color: #ccc;
  padding: 10px 0;
  height: 150px;
}

.modal-content,
#caption {
  animation-name: zoom;
  animation-duration: 0.6s;
}

@keyframes zoom {
  from {
    transform: scale(0)
  }
  to {
    transform: scale(1)
  }
}

.close {
  position: absolute;
  top: 15px;
  right: 35px;
  color: #f1f1f1;
  font-size: 40px;
  font-weight: bold;
  transition: 0.3s;
}

.close:hover,
.close:focus {
  color: #bbb;
  text-decoration: none;
  cursor: pointer;
}

@media only screen and (max-width: 700px) {
  .modal-content {
    width: 100%;
  }
}
<img class="myImages" id="myImg" src="http://onebigphoto.com/uploads/2012/10/midnight-sun-in-lofoten-norway.jpg" alt="Midnight sun in Lofoten, Norway" width="300" height="200">
<img class="myImages" id="myImg" src="http://cdn-image.travelandleisure.com/sites/default/files/styles/1600x1000/public/1490029386/fisherman-cabin-hamnoy-lofoten-islands-norway-NORWAY0320.jpg?itok=cpPuUjh1" alt="Fishermen's cabins in Lofoten, Norway"
width="300" height="200">
<img class="myImages" id="myImg" src="http://fjordtours.blob.core.windows.net/fjordtours-umbraco/1199/gerirangerfjord-per-ottar-walderhaug-fjordnorway.jpg" alt="Gerirangerfjord, Norway" width="300" height="200">
<div id="myModal" class="modal">
  <span class="close">&times;</span>
  <img class="modal-content" id="img01">
  <div id="caption"></div>
</div>
Snowmonkey
  • 3,716
  • 1
  • 16
  • 16
0

There is no need to duplicate modal div too, you can use a class name to select both images by using getElementsByClassName selector and then bind a click event to each one of them:

html

<img class="myImg" src="img_fjords.jpg" alt="Trolltunga, Norway">
<img class="myImg" src="img_mountains_wide.jpg" alt="Mountain, Norway">

js

// select images by class name
var img = document.getElementsByClassName('myImg');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");

// show modal function
var showModal = function(){
    modal.style.display = "block";
    modalImg.src = this.src;
    captionText.innerHTML = this.alt;
}

// bind click event to each img
for (var i = 0; i < img.length; i++) {
    img[i].addEventListener('click', showModal);
}

Here is a working example:

// Get the modal
var modal = document.getElementById('myModal');

// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementsByClassName('myImg');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");

var showModal = function(){
    modal.style.display = "block";
    modalImg.src = this.src;
    captionText.innerHTML = this.alt;
}

for (var i = 0; i < img.length; i++) {
    img[i].addEventListener('click', showModal);
}

// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];

// When the user clicks on <span> (x), close the modal
span.onclick = function() { 
    modal.style.display = "none";
}
#myImg {
    border-radius: 5px;
    cursor: pointer;
    transition: 0.3s;
}

#myImg:hover {opacity: 0.7;}

/* 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.9); /* Black w/ opacity */
}

/* Modal Content (image) */
.modal-content {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
}

/* Caption of Modal Image */
#caption {
    margin: auto;
    display: block;
    width: 80%;
    max-width: 700px;
    text-align: center;
    color: #ccc;
    padding: 10px 0;
    height: 150px;
}

/* Add Animation */
.modal-content, #caption {    
    -webkit-animation-name: zoom;
    -webkit-animation-duration: 0.6s;
    animation-name: zoom;
    animation-duration: 0.6s;
}

@-webkit-keyframes zoom {
    from {-webkit-transform:scale(0)} 
    to {-webkit-transform:scale(1)}
}

@keyframes zoom {
    from {transform:scale(0)} 
    to {transform:scale(1)}
}

/* The Close Button */
.close {
    position: absolute;
    top: 15px;
    right: 35px;
    color: #f1f1f1;
    font-size: 40px;
    font-weight: bold;
    transition: 0.3s;
}

.close:hover,
.close:focus {
    color: #bbb;
    text-decoration: none;
    cursor: pointer;
}

/* 100% Image Width on Smaller Screens */
@media only screen and (max-width: 700px){
    .modal-content {
        width: 100%;
    }
}
<img class="myImg" src="https://www.w3schools.com/howto/img_fjords.jpg" alt="Trolltunga, Norway" width="300" height="200">

<img class="myImg" src="https://www.w3schools.com/howto/img_mountains_wide.jpg" alt="Mountain, Norway" width="300" height="200">


<!-- The Modal -->
<div id="myModal" class="modal">
  <span class="close">&times;</span>
  <img class="modal-content" id="img01">
  <div id="caption"></div>
</div>
YouneL
  • 8,152
  • 2
  • 28
  • 50
0

You have to apply the class name ".modal-content" to your second image as well. The animation happens because of CSS Key Frames.

Or as an alternate - if your second image has a different class name or ID add it to the following CSS Code

.modal-content, #caption,<YOUR NEW IMAGE CLASS or ID> {
animation-name: zoom;
animation-duration: 0.6s;

}

0

This is an old question, but I came up with my own solution for this problem, using a data-modal HTML attribute.

document.querySelectorAll("img[data-modal]").forEach((img) => {
  var content = document.createElement("div"); //background
  content.className = "modal-content";
  content.appendChild(new Image()).src = img.src; //modal image
  img.insertAdjacentElement("afterend", content); //insert invisible content after image
  img.addEventListener("click", () => { //show modal on click
    content.style.opacity = "1";
    content.style.zIndex = "100";
    document.documentElement.style.overflow = "hidden"; //prevent scrolling while modal is shown
  });
  content.addEventListener("click", () => { //hide modal
    content.style.opacity = "";
    content.style.zIndex = "";
    document.documentElement.style.overflow = "";
  });
});
img[data-modal] {
  cursor: zoom-in;
}

.modal-content {
  z-index: -100; /* behind everything */
  opacity: 0; /* invisible */
  position: fixed;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.8); /* black, transparent */
  width: 100vw; /* 100% width */
  height: 100vh; /* 100% height */
  display: flex;
  justify-content: center; /* horizontal align */
  align-items: center; /* vertical align */
  transition: 0.5s; /* animate */
  cursor: zoom-out;
}

.modal-content img {
  min-width: 50vw; /* at least 50% of the viewport width */
  height: auto;
}
<h1>Press "Full Page" to see effect</h1>
<img 
  src="https://icatcare.org/app/uploads/2018/06/Layer-1704-1200x630.jpg" 
  data-modal 
/>
<img 
  src="https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/golden-retriever-royalty-free-image-506756303-1560962726.jpg?crop=0.672xw:1.00xh;0.166xw,0&resize=640:*" 
  data-modal 
/>

NOTE: This does not include a way to include a caption, but if you needed that you could replace the line content.appendChild(new Image()).src = img.src; with maybe:

var fig = document.createElement("figure");
fig.appendChild(new Image()).src = img.src;
fig.appendChild(document.createElement("figcaption")).textContent = img.alt;
content.appendChild(fig);

Then you could add some CSS to style your figure, maybe with text-align: center.