Gallery
by Jesse Johnson
HTML
<h1>Gallery Example</h1>
<div class="gallery">
<img data-src="https://picsum.photos/800/600.webp?random=1" alt="Gallery Image 1">
<img data-src="https://picsum.photos/800/600.webp?random=2" alt="Gallery Image 2">
<img data-src="https://picsum.photos/800/600.webp?random=3" alt="Gallery Image 3">
<img data-src="https://picsum.photos/800/600.webp?random=4" alt="Gallery Image 4">
<img data-src="https://picsum.photos/800/600.webp?random=5" alt="Gallery Image 5">
<img data-src="https://picsum.photos/800/600.webp?random=6" alt="Gallery Image 6">
<img data-src="https://picsum.photos/800/600.webp?random=7" alt="Gallery Image 7">
<img data-src="https://picsum.photos/800/600.webp?random=8" alt="Gallery Image 8">
<img data-src="https://picsum.photos/800/600.webp?random=9" alt="Gallery Image 9">
<img data-src="https://picsum.photos/800/600.webp?random=10" alt="Gallery Image 10">
<img data-src="https://picsum.photos/800/600.webp?random=11" alt="Gallery Image 11">
<img data-src="https://picsum.photos/800/600.webp?random=12" alt="Gallery Image 12">
<img data-src="https://picsum.photos/800/600.webp?random=13" alt="Gallery Image 13">
<img data-src="https://picsum.photos/800/600.webp?random=14" alt="Gallery Image 14">
<img data-src="https://picsum.photos/800/600.webp?random=15" alt="Gallery Image 15">
<img data-src="https://picsum.photos/800/600.webp?random=16" alt="Gallery Image 16">
<img data-src="https://picsum.photos/800/600.webp?random=17" alt="Gallery Image 17">
<img data-src="https://picsum.photos/800/600.webp?random=18" alt="Gallery Image 18">
<img data-src="https://picsum.photos/800/600.webp?random=19" alt="Gallery Image 19">
<img data-src="https://picsum.photos/800/600.webp?random=20" alt="Gallery Image 20">
<img data-src="https://picsum.photos/800/600.webp?random=21" alt="Gallery Image 21">
<img data-src="https://picsum.photos/800/600.webp?random=22" alt="Gallery Image 22">
<img...
CSS
body {
margin: 0;
font-family: "Georgia", serif;
background-color: #fff;
color: #333;
text-align: center;
padding: 2em;
}
h1 {
font-size: 1.8em;
margin-bottom: 1.5em;
font-weight: normal;
}
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
max-width: 1000px;
margin: 0 auto;
}
.gallery img {
width: 100%;
opacity: 0;
transition: opacity 1.2s ease-in-out;
border-radius: 8px;
}
.gallery img.loaded {
opacity: 1;
}
JavaScript
document.addEventListener("DOMContentLoaded", () => {
const images = document.querySelectorAll(".gallery img")
const observer = new IntersectionObserver(
(entries, obs) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target
img.src = img.dataset.src
img.onload = () => {
img.classList.add("loaded")
}
obs.unobserve(img)
}
})
},
{
threshold: 0.1,
},
)
images.forEach((img) => observer.observe(img))
})