Görsel Carousel ve Slider Performansı Nasıl Optimize Edilir
Carousel bileşenleri, modern web tasarımının en yaygın öğelerinden biridir; ürün galerileri, tanıtım bantları veya öne çıkan içerik blokları için neredeyse her projede karşınıza çıkar. Görsel açıdan etkileyici olan bu yapılar, performans tarafında ciddi bir sorun kaynağına dönüşebilir. Tek bir carousel bileşeni, sayfa yüklendiği anda görünmeyecek çok sayıda görsel indirebilir, gereksiz DOM işlemleri oluşturabilir ve kullanıcı etkileşimi olmaksızın bant genişliği tüketebilir.
Sorun yalnızca yavaş yüklemeyle sınırlı değildir. Görünümün dışındaki (viewport dışı) görsellerin önceden indirilmesi, özellikle mobil cihazlarda ağır bir yük oluşturur. Bir kullanıcı o görselleri hiç görmeden sayfayı kapatabilir; ama tarayıcı o ana kadar onlarca megabayt veri aktarmış olur. Bant genişliği israfı ile birlikte gelen ilk sayfa yükleme gecikmesi, hem kullanıcı deneyimini hem de arama motoru sıralamalarını doğrudan etkiler.
Performans optimizasyonu bu bağlamda bir tercih değil, temel bir mimari karardır. Carousel bileşeninin nasıl yapılandırıldığı, görsellerin ne zaman ve nasıl yüklendiği ile JavaScript kütüphanesinin ne kadar iş yaptığı, sayfa hızını belirleyen üç temel etkendir. Her birini ayrı ayrı ele almak gerekir.
Carousel bileşenleri neden hep performans sorunu yaratır?
Çoğu carousel kütüphanesi, bileşen başlatıldığında tüm slaytları DOM'a ekler ve hepsini aynı anda yükler. İlk slayt görünürdeyken üçüncü, dördüncü ve beşinci slaytların görselleri arka planda indirilmeye başlar. Tarayıcı bu görselleri kritik kaynaklar olarak algıladığından, LCP (Largest Contentful Paint) metriğini bozan bir yüklenme sırası oluşabilir.
Bir diğer yapısal sorun, JavaScript bağımlılığıdır. Carousel kütüphaneleri genellikle 20 ile 80 kilobayt arasında sıkıştırılmış JavaScript içerir ve bu kod sayfa yüklenir yüklenmez çalışmaya başlar. Otomatik oynatma etkinse, kütüphane sürekli bir zamanlayıcı çalıştırır, DOM mutasyonları tetikler ve animasyon döngüsünü yönetir. Kullanıcı carousel ile hiç etkileşime girmese bile bu işlem devam eder.
CSS animasyonları da yanlış yapılandırıldığında bileşik (composite) katman sayısını artırır. Her slayt ayrı bir katmana ayrılırsa GPU belleği şişer. Özellikle orta segment mobil cihazlarda bu durum animasyon takılmalarına, hatta sayfa çökmelerine yol açabilir.
Görünüm dışındaki görsellerin yüklenmesi: temel sorun
Carousel optimizasyonunun merkezinde tek bir soru yatar: hangi görseli ne zaman yükleyeceksiniz? Varsayılan davranış, tüm görselleri anında yüklemektir. Doğru yaklaşım, yalnızca aktif slaytı ve bir sonraki slaytı yüklemektir.
Bunu uygulamanın en güvenilir yolu, data-src kalıbını kullanmaktır. Görüntülenecek olmayan slaytların img etiketlerinde src yerine data-src kullanılır; slayt aktif hale geldikçe JavaScript bu değeri gerçek src'ye atar. Tarayıcı yalnızca src olan görselleri indirir.
<div class="slide" data-index="0">
<img src="slide-1.webp" alt="İlk slayt">
</div>
<div class="slide" data-index="1">
<img data-src="slide-2.webp" alt="İkinci slayt" width="1200" height="600">
</div>
<div class="slide" data-index="2">
<img data-src="slide-3.webp" alt="Üçüncü slayt" width="1200" height="600">
</div>
Slayt geçişi sırasında, bir sonraki slayt gösterilmeden hemen önce görsel yüklenmeye başlatılır. Bu, kullanıcının bir boşluk görmesini önlerken gereksiz ön yüklemeyi de engeller. Aktif slayt artı bir slayt önceden yüklemek, çoğu durumda yeterli bir tampon sağlar.
loading="lazy" neden carousel'de işe yaramaz?
Standart loading="lazy" özelliği, görüntü viewport'a yaklaştığında yüklemeyi tetikler. Carousel'in mantığı bu davranışla çelişir: tüm slaytlar DOM'da bulunur ama çoğu display: none veya opacity: 0 ile gizlidir. Tarayıcı bu gizli öğeleri "görünmüyor" olarak algılayabileceği gibi, bazı implementasyonlarda DOM'daki konumlarına bakarak viewport yakınlığını değerlendirip hepsini yükleyebilir de.
Sonuç öngörülemez. Bazı tarayıcılar gizli slaytları yüklememek için lazy'yi doğru yorumlar; bazıları tüm slaytları yükler. Bu tutarsız davranış, carousel için loading="lazy"'nin güvenilir bir çözüm olmadığını gösterir. Kontrollü JavaScript tabanlı ertelenmiş yükleme (deferred loading), carousel bağlamında çok daha tutarlı sonuç verir.
İlk slaytın görseli için durum farklıdır. O görsel her zaman loading="eager" ile veya hiçbir loading özelliği belirtilmeden yüklenmelidir, çünkü LCP hesaplamasına dahil olma olasılığı yüksektir. Öncelikli yükleme için <link rel="preload"> kullanmak da bir seçenektir.
JavaScript kütüphanesi seçimi ve hafifletme stratejileri
Carousel kütüphaneleri arasında dosya boyutu açısından ciddi farklar vardır. Popüler kütüphanelerin bir kısmı yalnızca slayt geçişi için 50 kilobaytın üzerinde JavaScript yükler. Gereksinimleriniz sadece temel geçişten ibaretse, özel bir çözüm yazmak kütüphane yükünü ortadan kaldırabilir.
Kütüphane kullanmaktan vazgeçemiyorsanız, ertelenmiş yükleme (deferred loading) uygulanabilir. Kütüphane kodu, kullanıcı carousel alanına scroll yaptığında veya carousel bileşenine dokunduğunda yüklenebilir. IntersectionObserver ile bu tetikleme şöyle kurulur:
const carouselEl = document.querySelector('.carousel');
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
import('./carousel-lib.js').then(({ initCarousel }) => {
initCarousel(carouselEl);
});
observer.disconnect();
}
}, { rootMargin: '200px' });
observer.observe(carouselEl);
Bu yaklaşımla carousel viewport'a 200 piksel yaklaştığında kütüphane yüklenir ve bileşen başlatılır. Sayfa ilk açıldığında carousel JavaScript'i indirilmez, ayrıştırılmaz, çalıştırılmaz. Özellikle carousel'in sayfa altındaki bir bölümde yer aldığı durumlarda bu yaklaşım belirgin bir ilk yükleme iyileştirmesi sağlar.
Görsel boyut ve format optimizasyonu
Carousel görselleri genellikle sayfanın en büyük görsellerini oluşturur. Tam genişlikli bir banner için 2500 piksel genişliğinde bir görsel yüklemek, mobil cihazlarda tamamen gereksizdir; ekran genişliği 390 piksel olan bir cihazda bu görsel ölçeklenerek gösterilir ama tam boyutuyla indirilir.
srcset ve sizes özellikleri bu sorunu çözer. Her görsel için farklı boyut varyantları üretilir ve tarayıcıya görüntüleme bağlamına göre uygun olanı seçme yetkisi verilir:
<img
src="slide-1-800.webp"
srcset="slide-1-400.webp 400w,
slide-1-800.webp 800w,
slide-1-1200.webp 1200w,
slide-1-1600.webp 1600w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 80vw,
1200px"
alt="Birinci slayt"
width="1200"
height="600">
Format seçimi de önemlidir. WebP, aynı görsel kalitesi için JPEG'den yaklaşık yüzde yirmi ile otuz daha az yer kaplar. AVIF daha iyi sıkıştırma sağlar ama tarayıcı desteği hâlâ evrensel değildir. picture öğesiyle her iki formatı birden sunabilir, tarayıcı desteklediğini seçer:
<picture>
<source srcset="slide-1.avif" type="image/avif">
<source srcset="slide-1.webp" type="image/webp">
<img src="slide-1.jpg" alt="Birinci slayt" width="1200" height="600">
</picture>
CLS sorunu ve boyut rezervasyonu
Carousel bileşenleri, CLS (Cumulative Layout Shift) metriğini bozan başlıca kaynaklardan biridir. Görsel boyutları belirtilmediğinde, görseller yüklenene kadar sıfır yüksekliğe sahip olabilir; yüklenince sayfa kayar. Bu kayma, Core Web Vitals puanını düşürür ve kullanıcının yanlışlıkla bir bağlantıya tıklamasına yol açabilir.
Çözüm basittir ama sıklıkla atlanır. width ve height özelliklerini her img etiketine eklemek, tarayıcının görsel yüklenmeden önce doğru alanı rezerv etmesini sağlar. Bu oran CSS'teki aspect-ratio hesaplamasında kullanılır.
Carousel sarmalayıcısı için de sabit bir en-boy oranı tanımlamak gerekir. Aksi halde, carousel başlatılmadan önce sıfır yükseklik gösterebilir ve JavaScript yüklenince tüm sayfa aşağı kayar. CSS ile bu rezervasyonu erken yapmak daha güvenlidir:
.carousel-wrapper {
aspect-ratio: 2 / 1;
width: 100%;
overflow: hidden;
}
Otomatik oynatma ve animasyon maliyeti
Otomatik oynatma özelliği hem kullanıcı deneyimi hem de performans açısından tartışmalıdır. Performans boyutuna bakıldığında, sürekli çalışan bir zamanlayıcı ve her geçişte tetiklenen DOM değişikliklerinin birikimli bir maliyet oluşturduğu görülür. Sayfa arka planda açıkken bile bu döngü devam edebilir.
Performans maliyetini azaltmak için iki yol vardır. İlki, Page Visibility API ile sayfa arka plana geçtiğinde zamanlayıcıyı durdurmaktır:
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
clearInterval(autoplayTimer);
} else {
autoplayTimer = setInterval(nextSlide, 4000);
}
});
İkincisi, prefers-reduced-motion medya sorgusuna saygı göstermektir. Bazı kullanıcılar işletim sistemi ayarlarında hareket azaltma tercihini etkinleştirmiştir; otomatik oynatma bu kullanıcılar için kapatılmalıdır. Bu hem erişilebilirlik hem de pil tüketimi açısından olumlu bir yaklaşımdır.
CSS animasyonlarında transform ve opacity kullanmak, left, top veya width gibi düzen hesaplaması tetikleyen özelliklerin önüne geçer. Yalnızca transform ile yapılan geçişler GPU üzerinde çalışır ve ana iş parçacığını (main thread) meşgul etmez.
Carousel ne zaman gereksizdir veya ters etki yaratır?
Performans optimizasyonu kadar önemli bir soru şudur: carousel gerçekten gerekli mi? Pek çok durumda carousel, içerik hiyerarşisini bulanıklaştırır ve ilk slayt dışındakilerin görüntülenme oranı oldukça düşük kalır. Kullanıcılar manuel olarak geçiş yapmak zorunda kaldıklarında ikinci slaytı nadiren görürler.
Ana sayfanın üst katlandaki (above the fold) alanında yer alan bir carousel, LCP'yi doğrudan etkiler. İlk slayt görsel olarak büyük ve yüklenmesi yavaşsa, LCP puanı düşer. Alternatif olarak tek bir sabit hero görseli, daha iyi LCP değeri, daha az JavaScript bağımlılığı ve daha tahmin edilebilir bir düzen sunar.
Ürün galerileri için carousel yerine CSS tabanlı yatay kaydırma (overflow-x: auto ile) düşünülebilir. Bu yaklaşım JavaScript gerektirmez, tüm görseller görünür olduğu için lazy loading kuralları doğru çalışır ve mobil kullanıcılar için doğal bir kaydırma deneyimi sunar. Carousel her proje için doğru araç değildir; seçim, içeriğin ne kadar önem taşıdığına ve kullanıcının hangi görseli gerçekten görmesi gerektiğine göre yapılır.
Carousel bileşenini tamamen kaldırmak mümkün değilse bile, görünüm dışındaki görsellerin ertelenmiş yüklenmesi, srcset ile boyut optimizasyonu ve JavaScript kütüphanesinin gecikmeli yüklenmesi, performans etkisini önemli ölçüde azaltır. Hangi stratejiyi seçeceğiniz, carousel'in sayfadaki konumuna, görsel sayısına ve hedef cihaz profiline göre değişir.
Sayfa yükleme sürelerini izlerken carousel'e özgü metriklere dikkat etmek gerekir: ilk slayt kaç milisaniyede yükleniyor, diğer slaytların arka planda yüklenmesi ağ bant genişliğini ne ölçüde tüketiyor, CLS değeri slayt geçişlerinden etkileniyor mu? Bu sorulara verilecek yanıtlar, hangi optimizasyonun öncelik taşıdığını netleştirir.