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+