
A fully responsive photo gallery that allows the user to open the images in a fullscreen lightbox with image descriptions and links.
Built with CSS, CSS Grid Layout, and Vanilla JavaScript.
How to use it:
1. Add images together with links (using data-url attribute as shown below) and descriptions to the photo gallery.
<section class="gallery">
<div class="container">
<h1 class="gallery-heading">MY Photo Gallery</h1>
<div class="gallery-grid">
<div class="gallery-item">
<img src="1.jpg" alt="Image 1">
<div class="gallery-item-text" data-url="https://cssscript.com">
Image Description 1
</div>
</div>
<div class="gallery-item">
<img src="2.jpg" alt="Image 2">
<div class="gallery-item-text" data-url="https://cssscript.com">
Image Description 2
</div>
</div>
<div class="gallery-item">
<img src="2.jpg" alt="Image 2">
<div class="gallery-item-text" data-url="https://cssscript.com">
Image Description 3
</div>
</div>
...
</div>
</div>
</section>2. The necessary CSS styles for the photo gallery.
img {
border: 0;
display: block; /* collapse top and bottom margins */
max-width: 100%;
}
.container {
margin: 0 auto;
max-width: 560px;
}
.gallery {
padding-bottom: 10px;
text-align: center;
}
.gallery-heading {
color: #00d6c8;
font-weight: 600;
letter-spacing: 0.1em;
line-height: 1.15;
text-transform: uppercase;
margin-top: 0;
position: relative;
padding-bottom: 8px;
}
.gallery-heading::after {
content: "";
background-color: currentColor;
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
height: 1px;
width: 100px;
}
.gallery-grid {
background: #283048;
background: linear-gradient(to right, #355460, #283048);
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-auto-rows: minmax(200px, -webkit-max-content);
grid-auto-rows: minmax(200px, max-content);
grid-auto-flow: dense;
gap: 10px;
margin-top: 40px;
padding: 10px;
}
.gallery-item img {
cursor: pointer;
-o-object-fit: cover;
object-fit: cover;
width: 100%;
height: 100%;
}
.gallery-item-text {
display: none;
}3. Create the HTML for the image lightbox.
<div class="lightbox preload">
<div class="lb-content">
<!-- You may put a loader gif or svg here for starters -->
<img class="lb-img" src="/img/loader.svg" alt="lightbox image">
<div class="lb-caption">
<a class="lb-url" href="" rel="noopener" target="_blank">Link to Site →</a>
<div class="lb-text"></div>
</div>
<a href="#" class="close">×</a>
</div>
</div>4. The necessary CSS styles for the image lightbox.
.lightbox {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
pointer-events: none;
transition: opacity 0.5s;
z-index: 10;
}
/* .preload will be removed by JS code during DOMContentLoaded event. This is done to avoid lightbox transition appearing on page load. */
.lightbox.preload {
transition: none !important;
}
.lightbox.open {
opacity: 1;
pointer-events: auto;
}
.lightbox .lb-content {
background-color: lightgray;
display: flex;
flex-direction: column;
justify-content: center;
margin: 1em;
max-height: 90%;
padding: 1rem;
position: relative;
}
.lightbox .lb-img {
-o-object-fit: contain;
object-fit: contain;
margin-bottom: 8px;
display: block;
width: 100%;
height: auto;
}
.lightbox .lb-caption {
color: #333;
display: flex;
flex-direction: column;
font-size: 0.9rem;
max-width: 50ch;
overflow-y: auto; /* may occur in smartphones */
opacity: 0;
transition: opacity 0.3s;
}
.lightbox.open .lb-caption {
opacity: 1;
}
.lightbox .lb-url {
color: #005fa9;
text-decoration: underline;
text-underline-position: under;
padding-top: 8px;
padding-bottom: 14px;
}
.lightbox .close {
background-color: lightgray;
cursor: pointer;
color: #333;
text-decoration: none;
display: inline-block;
font-size: 2em;
line-height: 1em;
text-align: center;
position: absolute;
top: -0.4em;
right: -0.4em;
width: 1em;
height: 1em;
border-radius: 50%;
}
/* Lightbox overlay */
.lightbox .close::before {
background-color: rgba(0, 0, 0, 0.9);
content: "";
cursor: default;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: -1;
}5. Make the photo gallery & image lightbox full responsive.
/* Medium devices (landscape tablets, 768px and up) */
@media screen and (min-width: 768px) {
.container {
max-width: 720px;
}
.lightbox .lb-caption {
font-size: 1rem;
}
}
/* Large devices (laptops/desktops, 1024px and up) */
@media screen and (min-width: 1024px) {
.container {
max-width: 960px;
}
.lightbox .lb-content {
flex-direction: row;
}
.lightbox .lb-img {
margin-bottom: 0;
}
.lightbox .lb-caption {
padding: 0 1.5em;
}
.lightbox .lb-url {
padding-top: 0;
}
}6. The core JavaScript to enable the image lightbox.
// Helper functions
let qs = (selector, context = document) => context.querySelector(selector);
let qsa = (selector, context = document) =>
Array.from(context.querySelectorAll(selector));
// Get gallery item into Lightbox
function openLightbox(e) {
const gitem = e.currentTarget,
itemimg = qs("img", gitem),
itemtext = qs(".gallery-item-text", gitem),
itemUrl = itemtext.dataset.url;
// Fill in the elements of lightbox.
const lightbox = qs(".lightbox"),
lightboximg = qs(".lb-img", lightbox),
lightboxtext = qs(".lb-text", lightbox),
lightboxDataURL = qs(".lb-url", lightbox);
lightboximg.onload = () => {
// fires as soon as image.src is assigned a URL.
lightboxtext.innerHTML = itemtext.innerHTML;
lightboxDataURL.setAttribute("href", itemUrl);
lightbox.classList.add("open");
};
// Assigns a relative url. This will fire onload.
lightboximg.setAttribute("src", itemimg.getAttribute("src"));
}
function closeLightbox(e) {
e.preventDefault();
const lightbox = e.currentTarget.closest(".lightbox");
lightbox.classList.remove("open");
}
document.addEventListener("DOMContentLoaded", () => {
const lightbox = qs(".lightbox.preload");
if (lightbox) lightbox.classList.remove("preload");
const gitems = qsa(".gallery-item");
gitems.forEach((el) => el.addEventListener("click", openLightbox));
const lbclose = qs(".lightbox .close");
if (lbclose) lbclose.addEventListener("click", closeLightbox);
});Changelog:
10/09/2020
- JS & CSS updated







