Proje Detayları

Adım Adım Geliştirme

Bu bölümde, resim galerisini adım adım nasıl geliştirebileceğinizi öğreneceksiniz. Her adımda, ilgili kod parçalarını ve açıklamalarını bulacaksınız.

Adım 1: Proje Yapısını Oluşturma

İlk olarak, projemiz için gerekli dosyaları oluşturalım:

  • index.html - Ana HTML dosyası
  • style.css - CSS stil dosyası
  • script.js - JavaScript kod dosyası
  • images - Resim dosyalarını içeren klasör
index.html
<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Resim Galerisi</title>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
    <div class="container">
        <div class="gallery-container">
            <div class="gallery-header">
                <h1>Resim Galerisi</h1>
                <p>Kategorilere göre filtreleyebilir veya arama yapabilirsiniz</p>
            </div>
            
            <div class="gallery-search">
                <input type="text" id="gallerySearch" placeholder="Resim ara...">
            </div>
            
            <div class="gallery-filters">
                <button class="filter-btn active" data-filter="all">Tümü</button>
                <button class="filter-btn" data-filter="nature">Doğa</button>
                <button class="filter-btn" data-filter="city">Şehir</button>
                <button class="filter-btn" data-filter="animals">Hayvanlar</button>
                <button class="filter-btn" data-filter="food">Yemek</button>
            </div>
            
            <div class="gallery-grid" id="galleryGrid">
                <!-- Resim öğeleri buraya dinamik olarak eklenecek -->
            </div>
            
            <!-- Resim Modalı -->
            <div class="gallery-modal" id="galleryModal">
                <div class="modal-content">
                    <span class="modal-close" id="modalClose">×</span>
                    <img src="" alt="" class="modal-img" id="modalImg">
                    <div class="modal-caption" id="modalCaption"></div>
                    <div class="modal-prev" id="modalPrev"><i class="fas fa-chevron-left"></i></div>
                    <div class="modal-next" id="modalNext"><i class="fas fa-chevron-right"></i></div>
                </div>
            </div>
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>
style.css
/* Genel Stiller */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f5f5f5;
    color: #333;
    line-height: 1.6;
}

.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

/* Galeri Stilleri */
.gallery-container {
    width: 100%;
}

.gallery-header {
    text-align: center;
    margin-bottom: 30px;
}

.gallery-header h1 {
    font-size: 2.5rem;
    color: #333;
    margin-bottom: 10px;
}

.gallery-header p {
    color: #666;
    font-size: 1.1rem;
}

.gallery-search {
    margin-bottom: 20px;
    display: flex;
}

.gallery-search input {
    flex: 1;
    padding: 10px 15px;
    border: 1px solid #ddd;
    border-radius: 25px;
    font-size: 1rem;
    outline: none;
}

.gallery-search input:focus {
    border-color: #4caf50;
}

.gallery-filters {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    margin-bottom: 20px;
}

.filter-btn {
    background-color: #f1f1f1;
    border: none;
    color: #333;
    padding: 8px 16px;
    margin: 5px;
    border-radius: 25px;
    cursor: pointer;
    transition: all 0.3s ease;
    font-size: 1rem;
}

.filter-btn:hover {
    background-color: #ddd;
}

.filter-btn.active {
    background-color: #4caf50;
    color: white;
}

.gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 20px;
}

.gallery-item {
    position: relative;
    overflow: hidden;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    cursor: pointer;
    height: 200px;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.gallery-item:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 16px rgba(0,0,0,0.2);
}

.gallery-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.5s ease;
}

.gallery-item:hover img {
    transform: scale(1.05);
}

.gallery-item-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0) 100%);
    color: white;
    padding: 15px;
    transform: translateY(100%);
    transition: transform 0.3s ease;
}

.gallery-item:hover .gallery-item-overlay {
    transform: translateY(0);
}

.gallery-item-title {
    font-size: 1.1rem;
    font-weight: bold;
    margin-bottom: 5px;
}

.gallery-item-category {
    font-size: 0.9rem;
    opacity: 0.8;
}

/* Modal Stilleri */
.gallery-modal {
    display: none;
    position: fixed;
    z-index: 1000;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    overflow: auto;
    background-color: rgba(0,0,0,0.9);
    opacity: 0;
    transition: opacity 0.3s ease;
}

.gallery-modal.show {
    display: flex;
    justify-content: center;
    align-items: center;
    opacity: 1;
}

.modal-content {
    position: relative;
    max-width: 80%;
    max-height: 80%;
}

.modal-img {
    display: block;
    max-width: 100%;
    max-height: 80vh;
    border: 3px solid white;
    box-shadow: 0 0 20px rgba(0,0,0,0.3);
}

.modal-caption {
    color: white;
    text-align: center;
    padding: 10px 0;
    font-size: 1.2rem;
}

.modal-close {
    position: absolute;
    top: -40px;
    right: 0;
    color: white;
    font-size: 30px;
    font-weight: bold;
    cursor: pointer;
}

.modal-prev, .modal-next {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    color: white;
    font-size: 30px;
    font-weight: bold;
    cursor: pointer;
    background-color: rgba(0,0,0,0.5);
    width: 50px;
    height: 50px;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: background-color 0.3s ease;
}

.modal-prev {
    left: -70px;
}

.modal-next {
    right: -70px;
}

.modal-prev:hover, .modal-next:hover {
    background-color: rgba(0,0,0,0.8);
}

/* Animasyonlar */
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
}

.gallery-item {
    animation: fadeIn 0.5s ease-out;
}

/* Responsive Tasarım */
@media (max-width: 768px) {
    .gallery-grid {
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }
    
    .modal-content {
        max-width: 95%;
    }
    
    .modal-prev, .modal-next {
        width: 40px;
        height: 40px;
        font-size: 24px;
    }
    
    .modal-prev {
        left: -50px;
    }
    
    .modal-next {
        right: -50px;
    }
}

@media (max-width: 480px) {
    .gallery-grid {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    }
    
    .gallery-item {
        height: 150px;
    }
    
    .modal-prev, .modal-next {
        position: fixed;
        top: auto;
        bottom: 20px;
        width: 40px;
        height: 40px;
    }
    
    .modal-prev {
        left: 20px;
    }
    
    .modal-next {
        right: 20px;
    }
}

Adım 2: Resim Verilerini Oluşturma

Şimdi, galeride kullanılacak resim verilerini oluşturalım:

script.js (Resim Verileri)
// Resim verileri
const galleryItems = [
    {
        id: 1,
        title: "Yeşil Orman",
        category: "nature",
        description: "Yemyeşil bir orman manzarası",
        imageSrc: "images/nature1.jpg"
    },
    {
        id: 2,
        title: "Dağ Manzarası",
        category: "nature",
        description: "Karlı dağların muhteşem manzarası",
        imageSrc: "images/nature2.jpg"
    },
    {
        id: 3,
        title: "Sahil Kenarı",
        category: "nature",
        description: "Masmavi deniz ve kumsal",
        imageSrc: "images/nature3.jpg"
    },
    {
        id: 4,
        title: "New York Manzarası",
        category: "city",
        description: "New York şehrinin gökdelenleri",
        imageSrc: "images/city1.jpg"
    },
    {
        id: 5,
        title: "Paris",
        category: "city",
        description: "Paris'te gün batımı",
        imageSrc: "images/city2.jpg"
    },
    {
        id: 6,
        title: "Tokyo",
        category: "city",
        description: "Tokyo'nun gece manzarası",
        imageSrc: "images/city3.jpg"
    },
    {
        id: 7,
        title: "Sevimli Kedi",
        category: "animals",
        description: "Tüylü sevimli bir kedi",
        imageSrc: "images/animal1.jpg"
    },
    {
        id: 8,
        title: "Vahşi Aslan",
        category: "animals",
        description: "Savanda bir aslan",
        imageSrc: "images/animal2.jpg"
    },
    {
        id: 9,
        title: "Renkli Papağan",
        category: "animals",
        description: "Renkli tüylere sahip bir papağan",
        imageSrc: "images/animal3.jpg"
    },
    {
        id: 10,
        title: "İtalyan Makarnası",
        category: "food",
        description: "Lezzetli İtalyan makarnası",
        imageSrc: "images/food1.jpg"
    },
    {
        id: 11,
        title: "Taze Meyveler",
        category: "food",
        description: "Taze ve renkli meyveler",
        imageSrc: "images/food2.jpg"
    },
    {
        id: 12,
        title: "Çikolatalı Pasta",
        category: "food",
        description: "Nefis çikolatalı pasta",
        imageSrc: "images/food3.jpg"
    }
];

İpucu: Yukarıdaki resim verileri örnek olarak verilmiştir. Kendi projelerinizde, Unsplash veya Pexels gibi sitelerden ücretsiz resimler kullanabilirsiniz. Dosya yollarını kendi resimlerinize göre güncellemeyi unutmayın.

Adım 3: JavaScript Kodunu Yazma

Şimdi, uygulamanın işlevselliğini sağlayacak JavaScript kodunu yazalım:

script.js (Ana Kod)
// DOM elementlerini seçme
const galleryGrid = document.getElementById('galleryGrid');
const gallerySearch = document.getElementById('gallerySearch');
const filterButtons = document.querySelectorAll('.filter-btn');
const galleryModal = document.getElementById('galleryModal');
const modalImg = document.getElementById('modalImg');
const modalCaption = document.getElementById('modalCaption');
const modalClose = document.getElementById('modalClose');
const modalPrev = document.getElementById('modalPrev');
const modalNext = document.getElementById('modalNext');

// Değişkenler
let currentFilter = 'all';
let currentIndex = 0;
let filteredItems = [...galleryItems];

// Sayfa yüklendiğinde
document.addEventListener('DOMContentLoaded', () => {
    // Galeri öğelerini oluştur
    renderGalleryItems();
    
    // Filtreleme butonları için olay dinleyicileri
    filterButtons.forEach(button => {
        button.addEventListener('click', () => {
            // Aktif butonu güncelle
            filterButtons.forEach(btn => btn.classList.remove('active'));
            button.classList.add('active');
            
            // Filtreleme yap
            currentFilter = button.getAttribute('data-filter');
            filterGalleryItems();
        });
    });
    
    // Arama kutusu için olay dinleyicisi
    gallerySearch.addEventListener('input', () => {
        filterGalleryItems();
    });
    
    // Modal kapatma butonu için olay dinleyicisi
    modalClose.addEventListener('click', closeModal);
    
    // Modal dışına tıklama olayı
    galleryModal.addEventListener('click', (e) => {
        if (e.target === galleryModal) {
            closeModal();
        }
    });
    
    // Önceki/sonraki butonları için olay dinleyicileri
    modalPrev.addEventListener('click', showPrevImage);
    modalNext.addEventListener('click', showNextImage);
    
    // Klavye olayları
    document.addEventListener('keydown', (e) => {
        if (galleryModal.classList.contains('show')) {
            if (e.key === 'Escape') {
                closeModal();
            } else if (e.key === 'ArrowLeft') {
                showPrevImage();
            } else if (e.key === 'ArrowRight') {
                showNextImage();
            }
        }
    });
});

// Galeri öğelerini oluşturma fonksiyonu
function renderGalleryItems() {
    galleryGrid.innerHTML = '';
    
    filteredItems.forEach((item, index) => {
        const galleryItem = document.createElement('div');
        galleryItem.className = 'gallery-item';
        galleryItem.setAttribute('data-category', item.category);
        galleryItem.setAttribute('data-index', index);
        
        galleryItem.innerHTML = `
            
            
                ${item.title}
                ${getCategoryName(item.category)}
            
        `;
        
        // Resme tıklama olayı
        galleryItem.addEventListener('click', () => {
            openModal(index);
        });
        
        galleryGrid.appendChild(galleryItem);
    });
}

// Kategori adını Türkçe olarak döndürme fonksiyonu
function getCategoryName(category) {
    const categories = {
        'nature': 'Doğa',
        'city': 'Şehir',
        'animals': 'Hayvanlar',
        'food': 'Yemek'
    };
    
    return categories[category] || category;
}

// Galeri öğelerini filtreleme fonksiyonu
function filterGalleryItems() {
    const searchTerm = gallerySearch.value.toLowerCase().trim();
    
    // Filtreleme ve arama
    filteredItems = galleryItems.filter(item => {
        // Kategori filtresi
        const categoryMatch = currentFilter === 'all' || item.category === currentFilter;
        
        // Arama filtresi
        const searchMatch = item.title.toLowerCase().includes(searchTerm) || 
                           item.description.toLowerCase().includes(searchTerm);
        
        return categoryMatch && searchMatch;
    });
    
    // Öğeleri yeniden oluştur
    renderGalleryItems();
}

// Modal açma fonksiyonu
function openModal(index) {
    currentIndex = index;
    updateModalContent();
    
    galleryModal.classList.add('show');
    document.body.style.overflow = 'hidden'; // Sayfanın kaydırılmasını engelle
}

// Modal kapatma fonksiyonu
function closeModal() {
    galleryModal.classList.remove('show');
    document.body.style.overflow = ''; // Sayfanın kaydırılmasını tekrar etkinleştir
}

// Modal içeriğini güncelleme fonksiyonu
function updateModalContent() {
    const item = filteredItems[currentIndex];
    
    modalImg.src = item.imageSrc;
    modalImg.alt = item.title;
    modalCaption.textContent = `${item.title} - ${item.description}`;
}

// Önceki resmi gösterme fonksiyonu
function showPrevImage() {
    currentIndex = (currentIndex - 1 + filteredItems.length) % filteredItems.length;
    updateModalContent();
}

// Sonraki resmi gösterme fonksiyonu
function showNextImage() {
    currentIndex = (currentIndex + 1) % filteredItems.length;
    updateModalContent();
}

// Dokunmatik kaydırma desteği
let touchStartX = 0;
let touchEndX = 0;

galleryModal.addEventListener('touchstart', (e) => {
    touchStartX = e.changedTouches[0].screenX;
});

galleryModal.addEventListener('touchend', (e) => {
    touchEndX = e.changedTouches[0].screenX;
    handleSwipe();
});

function handleSwipe() {
    const swipeThreshold = 50;
    
    if (touchEndX < touchStartX - swipeThreshold) {
        // Sola kaydırma - sonraki resim
        showNextImage();
    } else if (touchEndX > touchStartX + swipeThreshold) {
        // Sağa kaydırma - önceki resim
        showPrevImage();
    }
}

Adım 4: Uygulamayı Test Etme

Şimdi uygulamanızı test etme zamanı! Aşağıdaki adımları izleyin:

  1. Tüm dosyaları (index.htmlstyle.cssscript.js) aynı klasöre kaydedin.
  2. images klasörünü oluşturun ve içine resimlerinizi ekleyin.
  3. HTML dosyasını bir web tarayıcısında açın.
  4. Farklı kategori butonlarına tıklayarak filtreleme işlevini test edin.
  5. Arama kutusuna bir metin girerek arama işlevini test edin.
  6. Bir resme tıklayarak modalın açıldığını ve resmin büyük görüntülendiğini doğrulayın.
  7. Modal içinde önceki/sonraki butonlarını kullanarak resimler arasında geçiş yapın.
  8. Klavye ok tuşlarını kullanarak resimler arasında geçiş yapın.
  9. ESC tuşuna basarak veya modal dışına tıklayarak modalın kapandığını doğrulayın.
  10. Mobil cihazda veya dokunmatik ekranda kaydırma hareketlerini test edin.

İpucu: Tarayıcınızın geliştirici araçlarını (genellikle F12 tuşu ile açılır) kullanarak JavaScript hatalarını ayıklayabilirsiniz. Ayrıca, responsive tasarımı test etmek için tarayıcının ekran boyutunu değiştirebilirsiniz.

Projeyi Geliştirme

Temel resim galerisi uygulamasını başarıyla oluşturduktan sonra, aşağıdaki özelliklerle projenizi geliştirebilirsiniz:

1. Slayt Gösterisi Modu

Resimlerin otomatik olarak değiştiği bir slayt gösterisi modu ekleyin:

slideshow.js
// HTML'e slayt gösterisi butonu ekleyin
// <button id="slideshowBtn" class="slideshow-btn"><i class="fas fa-play"></i> Slayt Gösterisi</button>

// DOM elementlerini seç
const slideshowBtn = document.getElementById('slideshowBtn');

// Değişkenler
let slideshowInterval;
let isSlideshowActive = false;

// Olay dinleyicileri
slideshowBtn.addEventListener('click', toggleSlideshow);

// Slayt gösterisini başlatma/durdurma fonksiyonu
function toggleSlideshow() {
    if (isSlideshowActive) {
        stopSlideshow();
    } else {
        startSlideshow();
    }
}

// Slayt gösterisini başlatma fonksiyonu
function startSlideshow() {
    // Eğer modal açık değilse, ilk resmi göster
    if (!galleryModal.classList.contains('show')) {
        openModal(0);
    }
    
    // 3 saniyede bir resim değiştir
    slideshowInterval = setInterval(() => {
        showNextImage();
    }, 3000);
    
    // Buton stilini güncelle
    slideshowBtn.innerHTML = ' Duraklat';
    slideshowBtn.classList.add('active');
    
    isSlideshowActive = true;
}

// Slayt gösterisini durdurma fonksiyonu
function stopSlideshow() {
    clearInterval(slideshowInterval);
    
    // Buton stilini güncelle
    slideshowBtn.innerHTML = ' Slayt Gösterisi';
    slideshowBtn.classList.remove('active');
    
    isSlideshowActive = false;
}

// Modal kapatma fonksiyonunu güncelle
function closeModal() {
    galleryModal.classList.remove('show');
    document.body.style.overflow = '';
    
    // Eğer slayt gösterisi aktifse, durdur
    if (isSlideshowActive) {
        stopSlideshow();
    }
}

2. Masonry Düzeni

Farklı boyutlardaki resimleri daha iyi görüntülemek için Masonry düzeni ekleyin:

masonry.js
// CSS'i güncelle
// .gallery-grid {
//     display: grid;
//     grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
//     grid-auto-rows: 10px;
//     gap: 20px;
// }
//
// .gallery-item {
//     grid-row-end: span 20; /* Varsayılan yükseklik */
// }

// Masonry düzeni için resim yükleme sonrası yükseklik ayarlama
function setupMasonry() {
    const galleryItems = document.querySelectorAll('.gallery-item');
    
    galleryItems.forEach(item => {
        const img = item.querySelector('img');
        
        // Resim yüklendiğinde yüksekliği ayarla
        img.addEventListener('load', () => {
            const height = img.naturalHeight;
            const rowSpan = Math.ceil(height / 10 + 2); // 10px grid satırı + overlay için ek alan
            
            item.style.gridRowEnd = `span ${rowSpan}`;
        });
        
        // Eğer resim zaten yüklenmişse
        if (img.complete) {
            const height = img.naturalHeight;
            const rowSpan = Math.ceil(height / 10 + 2);
            
            item.style.gridRowEnd = `span ${rowSpan}`;
        }
    });
}

// Galeri öğelerini oluşturma fonksiyonunu güncelle
function renderGalleryItems() {
    galleryGrid.innerHTML = '';
    
    filteredItems.forEach((item, index) => {
        // ... mevcut kod ...
        
        galleryGrid.appendChild(galleryItem);
    });
    
    // Masonry düzenini ayarla
    setupMasonry();
}

3. Favorilere Ekleme

Kullanıcıların beğendikleri resimleri favorilere ekleyebilmesini sağlayın:

favorites.js
// HTML'e favoriler filtresi ekleyin
// <button class="filter-btn" data-filter="favorites">Favoriler</button>

// Değişkenler
let favorites = JSON.parse(localStorage.getItem('galleryFavorites')) || [];

// Galeri öğelerini oluşturma fonksiyonunu güncelle
function renderGalleryItems() {
    galleryGrid.innerHTML = '';
    
    filteredItems.forEach((item, index) => {
        const galleryItem = document.createElement('div');
        galleryItem.className = 'gallery-item';
        galleryItem.setAttribute('data-category', item.category);
        galleryItem.setAttribute('data-index', index);
        
        // Favori durumunu kontrol et
        const isFavorite = favorites.includes(item.id);
        
        galleryItem.innerHTML = `
            
            
                ${item.title}
                ${getCategoryName(item.category)}
                
                    
                
            
        `;
        
        // Resme tıklama olayı
        galleryItem.querySelector('img').addEventListener('click', () => {
            openModal(index);
        });
        
        // Favori butonuna tıklama olayı
        galleryItem.querySelector('.favorite-btn').addEventListener('click', (e) => {
            e.stopPropagation(); // Resme tıklama olayını engelle
            toggleFavorite(item.id);
        });
        
        galleryGrid.appendChild(galleryItem);
    });
}

// Favori durumunu değiştirme fonksiyonu
function toggleFavorite(id) {
    const index = favorites.indexOf(id);
    
    if (index === -1) {
        // Favorilere ekle
        favorites.push(id);
    } else {
        // Favorilerden çıkar
        favorites.splice(index, 1);
    }
    
    // LocalStorage'a kaydet
    localStorage.setItem('galleryFavorites', JSON.stringify(favorites));
    
    // Galeriyi güncelle
    filterGalleryItems();
}

// Galeri öğelerini filtreleme fonksiyonunu güncelle
function filterGalleryItems() {
    const searchTerm = gallerySearch.value.toLowerCase().trim();
    
    // Filtreleme ve arama
    filteredItems = galleryItems.filter(item => {
        // Kategori filtresi
        let categoryMatch = currentFilter === 'all' || item.category === currentFilter;
        
        // Favoriler filtresi
        if (currentFilter === 'favorites') {
            categoryMatch = favorites.includes(item.id);
        }
        
        // Arama filtresi
        const searchMatch = item.title.toLowerCase().includes(searchTerm) || 
                           item.description.toLowerCase().includes(searchTerm);
        
        return categoryMatch && searchMatch;
    });
    
    // Öğeleri yeniden oluştur
    renderGalleryItems();
}

Geliştirme Zorlukları

Resim galerisi uygulamanızı daha da geliştirmek için aşağıdaki zorlukları deneyebilirsiniz:

  1. Resim Yükleme: Kullanıcıların kendi resimlerini yükleyebilmesini sağlayan bir özellik ekleyin.
  2. Lightbox Efektleri: Farklı geçiş efektleri ve animasyonlar ekleyin.
  3. Resim Düzenleme: Basit filtreler (siyah-beyaz, sepya vb.) uygulayabilen bir düzenleme aracı ekleyin.
  4. Sosyal Paylaşım: Resimleri sosyal medyada paylaşma butonları ekleyin.
  5. Sürükle ve Bırak: Resimleri sürükleyip bırakarak yeniden düzenleyebilme özelliği ekleyin.

Sonuç ve Öğrenilen Dersler

Bu projede, JavaScript kullanarak etkileşimli bir resim galerisi uygulaması geliştirdik. Bu süreçte şunları öğrendik:

  • DOM manipülasyonu ile dinamik içerik oluşturmayı
  • Olay dinleyicileri ve olay yönetimini
  • CSS Grid kullanarak duyarlı bir galeri düzeni oluşturmayı
  • Filtreleme ve arama işlevselliği geliştirmeyi
  • Modal (açılır pencere) kullanarak resim görüntülemeyi
  • Animasyonlar ve geçişler ekleyerek kullanıcı deneyimini geliştirmeyi
  • Dokunmatik cihazlar için kaydırma desteği eklemeyi
  • Responsive tasarım ilkelerini uygulamayı

Bu proje, modern web geliştirme becerilerinizi geliştirmenize ve gerçek dünya uygulamaları oluşturmanıza yardımcı olacak temel bilgileri sağlamıştır. Öğrendiğiniz teknikleri ve kavramları kullanarak, daha karmaşık ve tam özellikli galeri uygulamaları geliştirebilirsiniz.