Merhaba arkadaşlar, bugün başımı çok ağrıtan bir sorunu ve onun temiz çözümünü paylaşmak istiyorum. Next.js'in Image component'i gerçekten harika, özellikle placeholder="blur" özelliği ile kullanıcı deneyimini inanılmaz iyileştiriyor. Ama bu özelliği kullanırken, blur görsel yüklenirken bile sayfada hafif bir oynama, yani layout shift yaşıyordum. Lighthouse skorumu düşüren bu can sıkıcı durumu çözmek için bulduğum kuralı anlatacağım.
Sorunun Kökeni: Blur Data URL ve Boyut Uyumsuzluğu
Sorun şuydu: placeholder="blur" kullandığınızda, bir de blurDataURL prop'unu sağlamanız gerekiyor. Bu blurDataURL, küçük boyutlu (örneğin 10px genişlikte) görselin base64 kodlanmış hali. İşte kritik nokta: Eğer Image component'inize verdiğiniz width/height değerleri ile, blurDataURL olarak verdiğiniz mini görselin oranları (aspect ratio) birbirini tutmazsa, Next.js önce blur placeholder'ı bu yanlış orana göre sığdırmaya çalışıyor. Asıl görsel yüklendiğinde ise doğru boyutlara geçiş yapılıyor ve bu da gözle görülür bir sıçramaya, layout shift'a neden oluyor.
Çözüm: Oranları Kilitlemek (Aspect Ratio Lock)
Çözüm aslında basit ama gözden kaçabiliyor. Hem Image component'inin width ve height prop'larını, hem de blurDataURL olarak kullanacağınız mini görseli, kesinlikle aynı en-boy oranında (aspect ratio) üretmelisiniz[/COLOR]. Yani gerçek görseliniz 1200x800 ise (oran 1.5), blurDataURL için oluşturacağınız 10px genişlikteki görsel de 10x6.66... olmalı. Piksel tam sayı olması için 10x7 veya 15x10 gibi yuvarlayabilirsiniz.
İşte bu kuralı uyguladığım temiz bir kod örneği:
Pratik İpucu: Blur Görseli Otomatik Üretmek
Her görsel için manuel olarak blur versiyonu oluşturmak zor olabilir. Ben şu yöntemi kullanıyorum: Projeme sharp kütüphanesini ekliyorum ve basit bir Node.js script'i yazıyorum. Bu script, `public` klasörümdeki tüm görsellerin 10px genişliğinde, oranı koruyarak blur versiyonlarını oluşturup base64'e çeviriyor. Bu base64 kodlarını bir JSON dosyasına kaydedip, component'lerimde import ederek kullanıyorum.
Basit bir script örneği:
Bu yöntemi uyguladıktan sonra, sayfalarımda Image component'leri artık hiç oynamıyor. Blur efekti pürüzsüz bir şekilde asıl görsele dönüşüyor ve Cumulative Layout Shift (CLS) skorum sıfıra yakın değerlere indi.
Siz Next.js'te Image component'i kullanırken benzer bir layout shift sorunu yaşadınız mı? Veya blur placeholder'lar için farklı, daha otomatik bir çözümünüz var mı? Yorumlarda paylaşalım!
Sorun şuydu: placeholder="blur" kullandığınızda, bir de blurDataURL prop'unu sağlamanız gerekiyor. Bu blurDataURL, küçük boyutlu (örneğin 10px genişlikte) görselin base64 kodlanmış hali. İşte kritik nokta: Eğer Image component'inize verdiğiniz width/height değerleri ile, blurDataURL olarak verdiğiniz mini görselin oranları (aspect ratio) birbirini tutmazsa, Next.js önce blur placeholder'ı bu yanlış orana göre sığdırmaya çalışıyor. Asıl görsel yüklendiğinde ise doğru boyutlara geçiş yapılıyor ve bu da gözle görülür bir sıçramaya, layout shift'a neden oluyor.
Çözüm aslında basit ama gözden kaçabiliyor. Hem Image component'inin width ve height prop'larını, hem de blurDataURL olarak kullanacağınız mini görseli, kesinlikle aynı en-boy oranında (aspect ratio) üretmelisiniz[/COLOR]. Yani gerçek görseliniz 1200x800 ise (oran 1.5), blurDataURL için oluşturacağınız 10px genişlikteki görsel de 10x6.66... olmalı. Piksel tam sayı olması için 10x7 veya 15x10 gibi yuvarlayabilirsiniz.
İşte bu kuralı uyguladığım temiz bir kod örneği:
JavaScript:
import Image from 'next/image';
import myImage from '../public/hero.jpg'; // Orjinal görsel: 1200x800 piksel (1.5 oran)
import blurImage from '../public/hero-blur.jpg'; // Blur için: 15x10 piksel (AYNI 1.5 oran!)
function MyComponent() {
return (
<div>
<Image
src={myImage}
alt="Hero Image"
width={1200}
height={800}
placeholder="blur"
blurDataURL={`data:image/jpeg;base64,${/ Buraya 15x10 görselin base64 kodu gelecek /}`}
// Veya doğrudan import ettiğiniz blurImage'ın src'sini kullanabilirsiniz.
/>
</div>
);
}
Her görsel için manuel olarak blur versiyonu oluşturmak zor olabilir. Ben şu yöntemi kullanıyorum: Projeme sharp kütüphanesini ekliyorum ve basit bir Node.js script'i yazıyorum. Bu script, `public` klasörümdeki tüm görsellerin 10px genişliğinde, oranı koruyarak blur versiyonlarını oluşturup base64'e çeviriyor. Bu base64 kodlarını bir JSON dosyasına kaydedip, component'lerimde import ederek kullanıyorum.
Basit bir script örneği:
JavaScript:
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
async function generateBlurDataURL(inputPath) {
const image = sharp(inputPath);
const metadata = await image.metadata(); // Orjinal boyutları al
// Oranı koruyarak genişliği 10px yap, yüksekliği orantılı hesapla
const blurWidth = 10;
const blurHeight = Math.round((metadata.height / metadata.width) blurWidth);
const buffer = await image
.resize(blurWidth, blurHeight)
.jpeg({ quality: 50 }) // Kaliteyi düşür
.toBuffer();
const base64 = buffer.toString('base64');
return `data:image/jpeg;base64,${base64}`;
}
// Kullanım örneği...
Bu yöntemi uyguladıktan sonra, sayfalarımda Image component'leri artık hiç oynamıyor. Blur efekti pürüzsüz bir şekilde asıl görsele dönüşüyor ve Cumulative Layout Shift (CLS) skorum sıfıra yakın değerlere indi.
Siz Next.js'te Image component'i kullanırken benzer bir layout shift sorunu yaşadınız mı? Veya blur placeholder'lar için farklı, daha otomatik bir çözümünüz var mı? Yorumlarda paylaşalım!