I have a gallery of images with some information appearing when you hover on each of them. When you click on each image, the full size is shown. I want to add a caption under the full-size versions based on the the information that appears when you hover on them.
For that purpose, I have made an array of caption texts. However, I am not able to figure out how I can assign the related caption to the respective image. I would also like to remove paragraph spacing from the caption.
To clarify, I added some images.
The texts that you see when you hover. Not the issue here.
The caption under the zoomed image. My Question:
Here is my code:
// Modal Images
var modal = document.getElementById("modalContainer");
var modalImg = document.getElementById("modalImg");
var imgArr = document.querySelectorAll(".img-container .img");
var currentIndex;
imgArr.forEach(function(img, i) {
img.onclick = function() {
var backgroundImage = img.style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
modal.style.display = "block";
modalImg.src = backgroundImage;
currentIndex = i;
};
});
// caption
var captionArr = [];
var captionInfo = document.querySelectorAll(".img-info");
var caption = document.getElementById("caption");
for (var i = 0; i < captionInfo.length; i++) {
var current = captionInfo[i];
console.log(current.textContent);
}
caption.innerHTML = captionArr[i];
console.log(captionArr);
// previous and next buttons
var prev = document.querySelector(".prev");
var next = document.querySelector(".next");
next.addEventListener("click", nextImage);
modalImg.addEventListener("click", nextImage);
function nextImage() {
if (currentIndex < imgArr.length - 1) {
currentIndex++;
modalImg.src = imgArr[currentIndex].style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
}
}
prev.addEventListener("click", previousImage);
function previousImage() {
if (currentIndex > 0) {
currentIndex--;
modalImg.src = imgArr[currentIndex].style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
}
}
// close the modal
var span = document.getElementsByClassName("close")[0];
span.addEventListener("click", close);
function close() {
modal.style.display = "none";
}
.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;
}
.img {
display: block;
width: 200px;
height: 100%;
margin-right: 10px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
}
.img-info {
display: block;
opacity: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 15px !important;
max-width: 80%;
}
.img-container:hover {
.img:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(0, 0, 0, 0.6);
}
.img-info {
opacity: 1;
}
}
.frame {
display: flex;
height: 100px;
min-height: 20rem;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
justify-content: center;
align-items: center;
}
.modal-content {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
max-height: 80%;
object-fit: contain;
-o-object-fit: contain;
animation-name: zoom;
animation-duration: 0.6s;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
width: auto;
padding: 0.8rem;
color: #777;
font-weight: normal;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
z-index: 3;
}
.prev:hover,
.next:hover {
color: #000;
}
.next {
right: 0;
}
.prev {
left: 0;
}
@keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
<div class="frame">
<div class="img-container">
<div class="img" style="background-image: url(https://images.unsplash.com/photo-1501159771943-cc9027db4d8b?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80)">
</div>
<div class="img-info">
<div class="img-info-title">
<h3>
Some text 1...
</h3>
</div>
<div class="img-info-subtitle">
<h4>
The rest 1...
</h4>
</div>
</div>
</div>
<div class="img-container">
<div class="img" style="background-image: url(https://images.unsplash.com/photo-1509042239860-f550ce710b93?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80">
</div>
<div class="img-info">
<div class="img-info-title">
<h3>
Some text 2...
</h3>
</div>
<div class="img-info-subtitle">
<h4>
The rest 2...
</h4>
</div>
</div>
</div>
<div class="img-container">
<div class="img" style="background-image: url(https://images.unsplash.com/photo-1583936410736-a4af4f3013d6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80)">
</div>
<div class="img-info">
<div class="img-info-title">
<h3>
Some text 3...
</h3>
</div>
<div class="img-info-subtitle">
<h4>
The rest 3...
</h4>
</div>
</div>
</div>
</div>
<!-- The Modal -->
<div id="modalContainer" class="modal">
<!-- Buttons -->
<span class="close">×</span>
<a class="prev">❮</a>
<a class="next">❯</a>
<!-- Modal Content -->
<img id="modalImg" class="modal-content">
<div class="caption">
<p id="caption"></p>
</div>
</div>
</div>
The first thing you can do is select the h3 and h4 and trim each of them to remove whitespace like:
console.log(current.querySelector('h3').textContent.trim() + " " + current.querySelector('h4').textContent.trim() );
// caption
var captionArr = [];
var captionInfo = document.querySelectorAll(".img-info");
var caption = document.getElementById("caption");
for (var i = 0; i < captionInfo.length; i++) {
var current = captionInfo[i];
var current_str = current.querySelector('h3').textContent.trim() + " " + current.querySelector('h4').textContent.trim();
console.log(current_str);
captionArr.push(current_str);
}
// Modal Images
var modal = document.getElementById("modalContainer");
var modalImg = document.getElementById("modalImg");
var imgArr = document.querySelectorAll(".img-container .img");
var currentIndex;
imgArr.forEach(function(img, i) {
img.onclick = function() {
var backgroundImage = img.style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
modal.style.display = "block";
modalImg.src = backgroundImage;
currentIndex = i;
console.log('i',i);
caption.innerHTML = captionArr[i];
};
});
// previous and next buttons
var prev = document.querySelector(".prev");
var next = document.querySelector(".next");
next.addEventListener("click", nextImage);
modalImg.addEventListener("click", nextImage);
function nextImage() {
if (currentIndex < imgArr.length - 1) {
currentIndex++;
modalImg.src = imgArr[currentIndex].style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
caption.innerHTML = captionArr[currentIndex];
}
}
prev.addEventListener("click", previousImage);
function previousImage() {
if (currentIndex > 0) {
currentIndex--;
modalImg.src = imgArr[currentIndex].style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
caption.innerHTML = captionArr[currentIndex];
}
}
// close the modal
var span = document.getElementsByClassName("close")[0];
span.addEventListener("click", close);
function close() {
modal.style.display = "none";
}
.img-info h3, .img-info h3,{
color: #f1f1f1;
opacity: 1 !important;
}
.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;
}
.img {
display: block;
width: 200px;
height: 100%;
margin-right: 10px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
}
.img-info {
display: block;
/*opacity: 0;*/
position: absolute;
/*top: 50%;*/
/*transform: translateY(-50%);*/
/*left: 15px !important;*/
max-width: 80%;
}
.img-container:hover {
.img:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background-color: rgba(0, 0, 0, 0.6);
}
.img-info {
opacity: 1;
}
}
.frame {
display: flex;
height: 100px;
min-height: 20rem;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
justify-content: center;
align-items: center;
}
.modal-content {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
max-height: 80%;
object-fit: contain;
-o-object-fit: contain;
animation-name: zoom;
animation-duration: 0.6s;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
width: auto;
padding: 0.8rem;
color: #777;
font-weight: normal;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
z-index: 3;
}
.prev:hover,
.next:hover {
color: #000;
}
.next {
right: 0;
}
.prev {
left: 0;
}
@keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
<div class="frame">
<div class="img-container">
<div class="img" style="background-image: url(https://images.unsplash.com/photo-1501159771943-cc9027db4d8b?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80)">
</div>
<div class="img-info">
<div class="img-info-title">
<h3>
Some text 1...
</h3>
</div>
<div class="img-info-subtitle">
<h4>
The rest 1...
</h4>
</div>
</div>
</div>
<div class="img-container">
<div class="img" style="background-image: url(https://images.unsplash.com/photo-1509042239860-f550ce710b93?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80">
</div>
<div class="img-info">
<div class="img-info-title">
<h3>
Some text 2...
</h3>
</div>
<div class="img-info-subtitle">
<h4>
The rest 2...
</h4>
</div>
</div>
</div>
<div class="img-container">
<div class="img" style="background-image: url(https://images.unsplash.com/photo-1583936410736-a4af4f3013d6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80)">
</div>
<div class="img-info">
<div class="img-info-title">
<h3>
Some text 3...
</h3>
</div>
<div class="img-info-subtitle">
<h4>
The rest 3...
</h4>
</div>
</div>
</div>
</div>
<!-- The Modal -->
<div id="modalContainer" class="modal">
<!-- Buttons -->
<span class="close">×</span>
<a class="prev">❮</a>
<a class="next">❯</a>
<!-- Modal Content -->
<img id="modalImg" class="modal-content">
<div class="caption">
<p id="caption" align="center" id="caption" style="color: white;"></p>
</div>
</div>
</div>
Note, I modified the CSS, removing a lot of what you had:
.img-info {
display: block;
/*opacity: 0;*/
position: absolute;
/*top: 50%;*/
/*transform: translateY(-50%);*/
/*left: 15px !important;*/
max-width: 80%;
}
Then we get the following:
I believe this is the desired behaviour.
Now to add under the model pop-up too I think.
To do this we need to modify the JS a bit (we need to create the captioArr first and push each string of text onto it. Then the index of that array matches the index of your forEach loop and so we can use caption.innerHTML = captionArr[i];
):
// caption
var captionArr = [];
var captionInfo = document.querySelectorAll(".img-info");
var caption = document.getElementById("caption");
for (var i = 0; i < captionInfo.length; i++) {
var current = captionInfo[i];
var current_str = current.querySelector('h3').textContent.trim() + " " + current.querySelector('h4').textContent.trim();
console.log(current_str);
captionArr.push(current_str);
}
// Modal Images
var modal = document.getElementById("modalContainer");
var modalImg = document.getElementById("modalImg");
var imgArr = document.querySelectorAll(".img-container .img");
var currentIndex;
imgArr.forEach(function(img, i) {
img.onclick = function() {
var backgroundImage = img.style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
modal.style.display = "block";
modalImg.src = backgroundImage;
currentIndex = i;
console.log('i',i);
caption.innerHTML = captionArr[i];
};
});
And then the style of the p tag a bit (it needs to be white and centred to see it)
<div class="caption">
<p id="caption" align="center" id="caption" style="color: white;"></p>
</div>
And then we get:
Finally, to change the caption when we click the previous and next buttons add one line to the prevImage and nextImage functions:
function nextImage() {
if (currentIndex < imgArr.length - 1) {
currentIndex++;
modalImg.src = imgArr[currentIndex].style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
caption.innerHTML = captionArr[currentIndex];
}
}
function previousImage() {
if (currentIndex > 0) {
currentIndex--;
modalImg.src = imgArr[currentIndex].style.backgroundImage
.slice(4, -1)
.replace(/"/g, "");
caption.innerHTML = captionArr[currentIndex];
}
}
Namely, caption.innerHTML = captionArr[currentIndex];