The below Tutorial worked and was tested with Bootstrap 5.0.2 – SUCCESS.
https://getbootstrap.com/docs/5.1/getting-started/download/
I implemented it in Production here: http://www.michaeleliasphotovoltaicsystems.com/projects.php
Note: FOUND A DIFFICULTY BUT – Got Error in Browser Console – SOLVED BY DOWNLOADING: bootstrap.min.css.map from
https://www.cdnpkg.com/twitter-bootstrap/file/bootstrap.min.css.map/
AND PUT IN THE SAME FOLDER AS \assets\css\bootstrap.min.css >>>>
JUST 4-STEPS
STEP 1 – HTML 5 – PUT IN HTML IN PLACE OF GALLERY APPEAR
<section class="image-grid"> <div class="container-xxl"> <div class="row gy-4"> <div class="col-12 col-sm-6 col-md-4"> <figure> <a class="d-block" href=""> <img width="1920" height="1280" src="ireland1.jpg" class="img-fluid" alt="Ring of Kerry, County Kerry, Ireland" data-caption="Ring of Kerry, County Kerry, Ireland"> </a> </figure> </div> <div class="col-12 col-sm-6 col-md-4"> <figure> <a class="d-block" href=""> <img width="1920" height="1280" src="ireland2.jpg" class="img-fluid" alt="Fintown, Ireland" data-caption="Fintown, Ireland"> </a> </figure> </div> <!-- more columns here --> </div> </div> </section>
STEP 2 – MODAL POPUP-WINDOW HTML5 – BUT IN THE END OF HTML
<div class="modal lightbox-modal" id="lightbox-modal" tabindex="-1"> <div class="modal-dialog modal-fullscreen"> <div class="modal-content"> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button> <div class="modal-body"> <div class="container-fluid p-0"> <!-- JS content here --> </div> </div> </div> </div> </div>
STEP 3 – CSS STYLES IN THE HEAD ELEMENT – PUT IN THE HEAD ABOVE </head>
/* BASIC STYLES –––––––––––––––––––––––––––––––––––––––––––––––––– */ :root { --lightbox: #242424; } body { margin: 24px 0 48px; font: 20px / 28px "Marck Script", cursive; } /* IMAGE GRID STYLES –––––––––––––––––––––––––––––––––––––––––––––––––– */ .image-grid figure { margin-bottom: 0; } .image-grid img { box-shadow: 0 1rem 1rem rgba(0, 0, 0, 0.15); transition: box-shadow 0.2s; } .image-grid a:hover img { box-shadow: 0 1rem 1rem rgba(0, 0, 0, 0.35); } /* LIGHTBOX STYLES –––––––––––––––––––––––––––––––––––––––––––––––––– */ .lightbox-modal .modal-content { background: var(--lightbox); } .lightbox-modal .btn-close { position: absolute; top: 20px; right: 18px; font-size: 1.2rem; z-index: 10; } .lightbox-modal .modal-body { display: flex; align-items: center; padding: 0; text-align: center; } .lightbox-modal img { width: auto; max-height: 100vh; max-width: 100%; } .lightbox-modal .carousel-caption { left: 0; right: 0; bottom: 0; background: rgba(36, 36, 36, 0.75); } .lightbox-modal .carousel-control-prev, .lightbox-modal .carousel-control-next { top: 50%; bottom: auto; transform: translateY(-50%); width: auto; } .lightbox-modal .carousel-control-prev { left: 10px; } .lightbox-modal .carousel-control-next { right: 10px; }
STEP 4 – FINAL JAVASCRIPT CODE – PUT AT THE END ABOVE </body>
const imageGrid = document.querySelector(".image-grid"); const links = imageGrid.querySelectorAll("a"); const imgs = imageGrid.querySelectorAll("img"); const lightboxModal = document.getElementById("lightbox-modal"); const bsModal = new bootstrap.Modal(lightboxModal); const modalBody = document.querySelector(".modal-body .container-fluid"); for (const link of links) { link.addEventListener("click", function (e) { e.preventDefault(); const currentImg = link.querySelector("img"); const lightboxCarousel = document.getElementById("lightboxCarousel"); if (lightboxCarousel) { const parentCol = link.parentElement.parentElement; const index = [...parentCol.parentElement.children].indexOf(parentCol); const bsCarousel = new bootstrap.Carousel(lightboxCarousel); bsCarousel.to(index); } else { createCarousel(currentImg); } bsModal.show(); }); } function createCarousel(img) { const markup = ` <div id="lightboxCarousel" class="carousel slide carousel-fade" data-bs-ride="carousel" data-bs-interval="false"> <div class="carousel-inner"> ${createSlides(img)} </div> <button class="carousel-control-prev" type="button" data-bs-target="#lightboxCarousel" data-bs-slide="prev"> <span class="carousel-control-prev-icon" aria-hidden="true"></span> <span class="visually-hidden">Previous</span> </button> <button class="carousel-control-next" type="button" data-bs-target="#lightboxCarousel" data-bs-slide="next"> <span class="carousel-control-next-icon" aria-hidden="true"></span> <span class="visually-hidden">Next</span> </button> </div> `; modalBody.innerHTML = markup; } function createSlides(img) { let markup = ""; const currentImgSrc = img.getAttribute("src"); for (const img of imgs) { const imgSrc = img.getAttribute("src"); const imgAlt = img.getAttribute("alt"); const imgCaption = img.getAttribute("data-caption"); markup += ` <div class="carousel-item${currentImgSrc === imgSrc ? " active" : ""}"> <img src=${imgSrc} alt=${imgAlt}> ${imgCaption ? createCaption(imgCaption) : ""} </div> `; } return markup; } function createCaption(caption) { return `<div class="carousel-caption"> <p class="m-0">${caption}</p> </div>`; }