Animated Image Gallery
Intermediate
Modern image gallery with filtering, sorting, and lightbox functionality, perfect for showcasing portfolios and photo collections.
Live Preview
Code Implementation
HTML
<div class="image-gallery-container">
<div class="image-gallery-demo">
<div class="gallery-header">
<h2>Image Gallery</h2>
<p>Beautiful photo collection with filtering</p>
</div>
<div class="gallery-controls">
<div class="filter-buttons">
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="nature">Nature</button>
<button class="filter-btn" data-filter="urban">Urban</button>
<button class="filter-btn" data-filter="people">People</button>
<button class="filter-btn" data-filter="abstract">Abstract</button>
</div>
<div class="sort-dropdown">
<select id="sortSelect">
<option value="newest">Newest First</option>
<option value="oldest">Oldest First</option>
<option value="name">Name A-Z</option>
</select>
</div>
</div>
<div class="gallery-grid" id="galleryGrid">
<!-- Gallery items will be dynamically inserted here -->
</div>
<div class="gallery-footer">
<div class="pagination-info">
Showing <span id="currentCount">0</span> of <span id="totalCount">0</span> images
</div>
</div>
</div>
</div>
<!-- Lightbox -->
<div class="lightbox" id="lightbox">
<div class="lightbox-content">
<button class="lightbox-close" id="lightboxClose">×</button>
<button class="lightbox-nav prev" id="lightboxPrev">‹</button>
<button class="lightbox-nav next" id="lightboxNext">›</button>
<div class="lightbox-image-container">
<img class="lightbox-image" id="lightboxImage" src="" alt="">
<div class="lightbox-caption" id="lightboxCaption"></div>
</div>
</div>
</div>
CSS
.image-gallery-container {
background: linear-gradient(135deg, #f8f9ff 0%, #ffffff 100%);
padding: 40px 20px;
border-radius: 20px;
max-width: 1200px;
margin: 0 auto;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.05);
}
.image-gallery-demo {
background: white;
border-radius: 15px;
padding: 30px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.03);
}
.gallery-header {
text-align: center;
margin-bottom: 30px;
}
.gallery-header h2 {
margin: 0 0 10px 0;
color: #333;
font-size: 2rem;
font-weight: 700;
}
.gallery-header p {
color: #666;
font-size: 1.1rem;
margin: 0;
}
.gallery-controls {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
margin-bottom: 30px;
padding: 20px;
background: #f8fafc;
border-radius: 15px;
}
.filter-buttons {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.filter-btn {
padding: 10px 20px;
background: white;
border: 2px solid #e2e8f0;
border-radius: 30px;
color: #666;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.filter-btn:hover,
.filter-btn.active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-color: transparent;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.sort-dropdown select {
padding: 10px 15px;
border: 2px solid #e2e8f0;
border-radius: 8px;
background: white;
color: #333;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
.sort-dropdown select:hover {
border-color: #667eea;
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.2);
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 25px;
margin-bottom: 30px;
}
.gallery-item {
position: relative;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
aspect-ratio: 4/3;
}
.gallery-item:hover {
transform: translateY(-10px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.gallery-item:hover img {
transform: scale(1.1);
}
.gallery-item .overlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent);
color: white;
padding: 25px 20px 20px;
opacity: 0;
transition: opacity 0.3s ease;
}
.gallery-item:hover .overlay {
opacity: 1;
}
.gallery-item .title {
font-weight: 700;
font-size: 1.1rem;
margin-bottom: 8px;
}
.gallery-item .category {
font-size: 0.9rem;
opacity: 0.8;
text-transform: uppercase;
letter-spacing: 1px;
font-weight: 600;
}
.gallery-item .tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 15px;
}
.gallery-item .tag {
background: rgba(255, 255, 255, 0.2);
padding: 4px 12px;
border-radius: 20px;
font-size: 0.8rem;
backdrop-filter: blur(10px);
}
.gallery-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background: #f8fafc;
border-radius: 15px;
}
.pagination-info {
color: #666;
font-size: 1rem;
font-weight: 500;
}
/* Lightbox styles */
.lightbox {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
display: none;
align-items: center;
justify-content: center;
z-index: 10000;
backdrop-filter: blur(10px);
}
.lightbox-content {
position: relative;
max-width: 90%;
max-height: 90%;
width: auto;
height: auto;
}
.lightbox-close {
position: absolute;
top: -50px;
right: 0;
background: none;
border: none;
color: white;
font-size: 3rem;
cursor: pointer;
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
}
.lightbox-close:hover {
background: rgba(255, 255, 255, 0.1);
transform: rotate(90deg);
}
.lightbox-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0.2);
color: white;
border: none;
width: 60px;
height: 60px;
border-radius: 50%;
font-size: 2rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
}
.lightbox-nav:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-50%) scale(1.1);
}
.lightbox-nav.prev {
left: -80px;
}
.lightbox-nav.next {
right: -80px;
}
.lightbox-image-container {
position: relative;
max-width: 800px;
max-height: 600px;
}
.lightbox-image {
max-width: 100%;
max-height: 100%;
border-radius: 10px;
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
}
.lightbox-caption {
position: absolute;
bottom: -60px;
left: 0;
right: 0;
text-align: center;
color: white;
font-size: 1.2rem;
font-weight: 600;
padding: 20px;
}
/* Loading animation */
.gallery-item.loading {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}
.gallery-item.loading img {
visibility: hidden;
}
@keyframes loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
/* Animations */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes zoomIn {
from {
opacity: 0;
transform: scale(0.8);
}
to {
opacity: 1;
transform: scale(1);
}
}
.gallery-item {
animation: fadeInUp 0.6s ease-out;
}
.gallery-item:nth-child(1) { animation-delay: 0.1s; }
.gallery-item:nth-child(2) { animation-delay: 0.2s; }
.gallery-item:nth-child(3) { animation-delay: 0.3s; }
.gallery-item:nth-child(4) { animation-delay: 0.4s; }
.gallery-item:nth-child(5) { animation-delay: 0.5s; }
.gallery-item:nth-child(6) { animation-delay: 0.6s; }
/* Responsive */
@media (max-width: 768px) {
.image-gallery-container {
padding: 30px 15px;
}
.image-gallery-demo {
padding: 25px;
}
.gallery-header h2 {
font-size: 1.7rem;
}
.gallery-controls {
flex-direction: column;
align-items: stretch;
gap: 15px;
}
.filter-buttons {
justify-content: center;
}
.gallery-grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
}
.gallery-item {
aspect-ratio: 3/2;
}
.gallery-footer {
flex-direction: column;
gap: 15px;
text-align: center;
}
.lightbox-nav.prev {
left: 20px;
}
.lightbox-nav.next {
right: 20px;
}
.lightbox-close {
top: 20px;
right: 20px;
}
}
@media (max-width: 480px) {
.gallery-grid {
grid-template-columns: 1fr;
}
.filter-buttons {
flex-wrap: wrap;
}
.filter-btn {
flex: 1;
min-width: 120px;
padding: 8px 15px;
font-size: 0.85rem;
}
.lightbox-nav {
width: 50px;
height: 50px;
font-size: 1.5rem;
}
.lightbox-nav.prev {
left: 10px;
}
.lightbox-nav.next {
right: 10px;
}
.lightbox-caption {
font-size: 1rem;
bottom: -50px;
}
}
JavaScript
document.addEventListener('DOMContentLoaded', function() {
// Get DOM elements
const galleryGrid = document.getElementById('galleryGrid');
const filterButtons = document.querySelectorAll('.filter-btn');
const sortSelect = document.getElementById('sortSelect');
const lightbox = document.getElementById('lightbox');
const lightboxImage = document.getElementById('lightboxImage');
const lightboxCaption = document.getElementById('lightboxCaption');
const lightboxClose = document.getElementById('lightboxClose');
const lightboxPrev = document.getElementById('lightboxPrev');
const lightboxNext = document.getElementById('lightboxNext');
const currentCount = document.getElementById('currentCount');
const totalCount = document.getElementById('totalCount');
// Sample gallery data
const galleryData = [
{
id: 1,
title: "Mountain Landscape",
category: "nature",
tags: ["landscape", "mountains", "sunset"],
url: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&h=400&fit=crop",
date: "2023-05-15"
},
{
id: 2,
title: "Urban Skyline",
category: "urban",
tags: ["city", "skyline", "night"],
url: "https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?w=600&h=400&fit=crop",
date: "2023-06-22"
},
{
id: 3,
title: "Portrait of Jane",
category: "people",
tags: ["portrait", "woman", "smile"],
url: "https://images.unsplash.com/photo-1494790108755-2616b612b786?w=600&h=400&fit=crop",
date: "2023-07-10"
},
{
id: 4,
title: "Forest Pathway",
category: "nature",
tags: ["forest", "trees", "path"],
url: "https://images.unsplash.com/photo-1448375240586-882707db888b?w=600&h=400&fit=crop",
date: "2023-08-05"
},
{
id: 5,
title: "City Lights",
category: "urban",
tags: ["city", "lights", "night"],
url: "https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?w=600&h=400&fit=crop",
date: "2023-09-18"
},
{
id: 6,
title: "Beach Sunset",
category: "nature",
tags: ["beach", "sunset", "ocean"],
url: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=600&h=400&fit=crop",
date: "2023-10-30"
},
{
id: 7,
title: "Business Meeting",
category: "people",
tags: ["business", "meeting", "office"],
url: "https://images.unsplash.com/photo-1551836022-d5d88e9218df?w=600&h=400&fit=crop",
date: "2023-11-12"
},
{
id: 8,
title: "Street Art",
category: "urban",
tags: ["street", "art", "graffiti"],
url: "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?w=600&h=400&fit=crop",
date: "2023-12-03"
},
{
id: 9,
title: "Coffee Shop",
category: "people",
tags: ["coffee", "shop", "cafe"],
url: "https://images.unsplash.com/photo-1554866585-cd94860890b7?w=600&h=400&fit=crop",
date: "2024-01-15"
},
{
id: 10,
title: "Desert Dunes",
category: "nature",
tags: ["desert", "dunes", "sand"],
url: "https://images.unsplash.com/photo-1509316785289-025f5b8b4c06?w=600&h=400&fit=crop",
date: "2024-02-20"
},
{
id: 11,
title: "Modern Architecture",
category: "urban",
tags: ["architecture", "building", "modern"],
url: "https://images.unsplash.com/photo-1494790108755-2616b612b786?w=600&h=400&fit=crop",
date: "2024-03-08"
},
{
id: 12,
title: "Family Portrait",
category: "people",
tags: ["family", "portrait", "love"],
url: "https://images.unsplash.com/photo-1511942142245-1e43b0b2d7d9?w=600&h=400&fit=crop",
date: "2024-04-17"
}
];
// State management
let currentFilter = 'all';
let currentSort = 'newest';
let currentImageIndex = 0;
let filteredData = [];
// Initialize gallery
function initGallery() {
renderGallery();
setupEventListeners();
}
// Setup event listeners
function setupEventListeners() {
// Filter buttons
filterButtons.forEach(button => {
button.addEventListener('click', function() {
filterButtons.forEach(btn => btn.classList.remove('active'));
this.classList.add('active');
currentFilter = this.getAttribute('data-filter');
renderGallery();
});
});
// Sort dropdown
sortSelect.addEventListener('change', function() {
currentSort = this.value;
renderGallery();
});
// Lightbox controls
lightboxClose.addEventListener('click', closeLightbox);
lightboxPrev.addEventListener('click', showPrevImage);
lightboxNext.addEventListener('click', showNextImage);
// Close lightbox when clicking outside image
lightbox.addEventListener('click', function(e) {
if (e.target === lightbox) {
closeLightbox();
}
});
// Keyboard navigation
document.addEventListener('keydown', function(e) {
if (lightbox.style.display === 'flex') {
if (e.key === 'Escape') {
closeLightbox();
} else if (e.key === 'ArrowLeft') {
showPrevImage();
} else if (e.key === 'ArrowRight') {
showNextImage();
}
}
});
}
// Render gallery
function renderGallery() {
// Filter data
filteredData = currentFilter === 'all' ?
[...galleryData] :
galleryData.filter(item => item.category === currentFilter);
// Sort data
filteredData.sort((a, b) => {
switch (currentSort) {
case 'newest':
return new Date(b.date) - new Date(a.date);
case 'oldest':
return new Date(a.date) - new Date(b.date);
case 'name':
return a.title.localeCompare(b.title);
default:
return 0;
}
});
// Clear grid
galleryGrid.innerHTML = '';
// Render items
filteredData.forEach((item, index) => {
const galleryItem = document.createElement('div');
galleryItem.className = 'gallery-item loading';
galleryItem.innerHTML = `
<img src="${item.url}" alt="${item.title}" onload="this.parentElement.classList.remove('loading')">
<div class="overlay">
<div class="title">${item.title}</div>
<div class="category">${item.category}</div>
<div class="tags">
${item.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
</div>
</div>
`;
// Add click event for lightbox
galleryItem.addEventListener('click', () => {
openLightbox(index);
});
galleryGrid.appendChild(galleryItem);
});
// Update counts
currentCount.textContent = filteredData.length;
totalCount.textContent = galleryData.length;
}
// Open lightbox
function openLightbox(index) {
currentImageIndex = index;
const item = filteredData[index];
lightboxImage.src = item.url;
lightboxCaption.textContent = item.title;
lightbox.style.display = 'flex';
document.body.style.overflow = 'hidden';
// Add animation
lightboxContent.style.animation = 'zoomIn 0.3s ease-out';
}
// Close lightbox
function closeLightbox() {
lightbox.style.display = 'none';
document.body.style.overflow = 'auto';
}
// Show previous image
function showPrevImage() {
currentImageIndex = (currentImageIndex - 1 + filteredData.length) % filteredData.length;
const item = filteredData[currentImageIndex];
lightboxImage.src = item.url;
lightboxCaption.textContent = item.title;
// Add navigation animation
lightboxImage.style.animation = 'fadeIn 0.3s ease-out';
setTimeout(() => {
lightboxImage.style.animation = '';
}, 300);
}
// Show next image
function showNextImage() {
currentImageIndex = (currentImageIndex + 1) % filteredData.length;
const item = filteredData[currentImageIndex];
lightboxImage.src = item.url;
lightboxCaption.textContent = item.title;
// Add navigation animation
lightboxImage.style.animation = 'fadeIn 0.3s ease-out';
setTimeout(() => {
lightboxImage.style.animation = '';
}, 300);
}
// Initialize the gallery
initGallery();
});
Snippet Features
Browser Compatibility
🟢
chrome 50+ 🟠
firefox 45+ 🔵
safari 10+ 🟦
edge 15+