Puppeteer kullanarak bir web sitesinin tam sayfa ekran görüntüsünü almaya çalıştığınızda, sabit (position: fixed) bir başlıkla karşılaşabilirsiniz. Neyse ki, bu durumun ardındaki teknik nedenler ve çözümleri artık daha anlaşılır hale geldi.
Sorun, Puppeteer'in fullPage: true seçeneğinin Chrome'un Geliştirici Araçları Protokolü (captureBeyondViewport) üzerinden çalışmasından kaynaklanıyor. Bu mekanizma, sayfanın tamamını görüntülemek için tüm belgeyi rasterize ederken, sabit öğelerin konumunu görünüm alanına (viewport) göre değil, belgeye göre belirlemesiyle ilgili bir uyumsuzluk ortaya çıkıyor. Başka bir deyişle, eğer script sayfanın en altına kaydırılmışsa, sabit başlık da ekranın en altına konumlanıyor ve ekran görüntüsünde orta kısımda ya da boşlukta kalıyor.
Neden bu sorun ortaya çıkıyor?
Sabit konumlu öğelerin davranışı, Puppeteer'in tam sayfa ekran görüntüsü alma sürecinde iki temel soruna yol açıyor:
- Görünüm alanı dışında kalan sabit öğeler: Chrome, belgeyi rasterize ederken sabit öğeleri görünüm alanına göre konumlandırdığı için, sayfanın kaydırılmış olması durumunda bu öğeler ekranın dışında kalıyor.
- Düzgün kaydırma animasyonları: Birçok modern web sitesinde
htmlveyabodyöğelerinescroll-behavior: smoothuygulanır. Puppeteer,window.scrollTo(0, 0)komutunu çalıştırdığında, bu kaydırma animasyonu tamamlanmadan ekran görüntüsü alınabilir. Sonuç olarak, başlık ekranın ortasında ya da kaydırma sırasında geçici bir konumda görünür.
Bu iki durum, ekran görüntüsünde başlığın doğru yerde görünmemesine neden oluyor. Neyse ki, bu sorunların her ikisi de kod düzeyinde çözülebilir.
Basit ve etkili çözüm adımları
Sabit başlığın tam sayfa ekran görüntüsünde doğru bir şekilde görünmesini sağlamak için üç temel adım izlemeniz gerekiyor:
- Düzgün kaydırma animasyonunu devre dışı bırakın: Düzgün kaydırma efektini kaldırmak,
scrollTokomutunun anında çalışmasını sağlar. Bu sayede, Puppeteer ekran görüntüsünü alırken başlıkta herhangi bir geçici konum sorunu yaşanmaz.
- Kaydırma olaylarına bağlı gizlenen öğeleri sıfırlayın: Birçok web sitesinde, kaydırma olaylarına tepki olarak başlıklar gizlenir. Bu durumda, başlığın görünürlüğünü ve konumunu düzeltilmesi gerekebilir.
- Sayfayı en üste kaydırın ve render işlemini tamamlayın: Sayfayı en üste kaydırdıktan sonra, tarayıcının render işlemini tamamlaması için kısa bir bekleme süresi ekleyin.
Aşağıda, üretim ortamında kullanılan hazırlama fonksiyonunu bulabilirsiniz. Bu fonksiyon, yukarıdaki tüm adımları otomatik olarak gerçekleştiriyor:
async function prepareForScreenshot(page) {
await page.evaluate(() => {
// Düzgün kaydırma animasyonunu devre dışı bırakın — scrollTo komutunu anında çalıştırın
const style = document.createElement('style');
style.textContent = 'html { scroll-behavior: auto !important; }';
document.head.appendChild(style);
// Kaydırma olaylarına bağlı gizlenen sabit başlıkları sıfırlayın
const headers = document.querySelectorAll(
'header, .header, [class*="header" i], nav[class*="header" i]'
);
headers.forEach(el => {
const cs = window.getComputedStyle(el);
if (cs.position === 'fixed' || cs.position === 'sticky') {
el.style.setProperty('transform', 'none', 'important');
el.style.setProperty('opacity', '1', 'important');
el.style.setProperty('visibility', 'visible', 'important');
if (cs.display === 'none') {
el.style.setProperty('display', 'flex', 'important');
}
// Kaydırma olaylarına bağlı gizlenen sınıfları kaldırın
['hidden', 'is-hidden', 'scroll-up', 'scroll-down', 'header--hidden']
.forEach(c => el.classList.remove(c));
}
});
// Sayfayı en üste kaydırın — artık anında çalışıyor
window.scrollTo(0, 0);
});
// Tarayıcının render işlemini tamamlaması için kısa bir süre bekleyin
await new Promise(r => setTimeout(r, 300));
}Bu fonksiyonu, ekran görüntüsü almadan hemen önce çağırmanız gerekiyor:
await prepareForScreenshot(page);
await page.screenshot({ path: 'out.png', fullPage: true });Daha karmaşık durumlar için ek adımlar
Yukarıdaki çözüm, çoğu modern web sitesinde başarıyla çalışıyor. Ancak bazı durumlarda, özellikle de şeffaf bir başlığın kahraman bölümünün üzerinde yer aldığı tasarımlarda, ilave adımlara ihtiyaç duyulabilir. Bu tür durumlarda, başlığın kahraman bölümün üzerinde doğru şekilde görüntülenmesi için genellikle yeterli oluyor.
Bazı web siteleri, kaydırma olaylarına tepki veren JavaScript kütüphaneleri kullanır. Bu kütüphaneler, başlığın gizlenmesini ya da görünürlüğünü kaydırma olaylarına bağlı olarak ayarlar. Eğer hazırlama fonksiyonunu çalıştırdıktan sonra bile başlık doğru şekilde görünmüyorsa, sentetik bir kaydırma olayı göndererek bu kütüphanelerin yeniden değerlendirme yapmasını sağlayabilirsiniz:
window.scrollTo(0, 0);
window.dispatchEvent(new Event('scroll'));Gelecekteki projeler ve geribildirimler
Bu sorunun kök nedenini ve çözümünü araştırırken, Site2PDF adlı bir araç üzerinde çalıştım. Bu araç, herhangi bir web sitesini PDF, PNG, JPG veya ZIP formatlarına dönüştürmenize olanak tanıyor. Hazırladığımız fonksiyon, bu aracın üretim ortamında kullanılan temel bileşenlerinden biri. Ücretsiz planımızda ayda 5 arşiv oluşturma hakkı sunarken, tüm formatlara ve gelişmiş seçeneklere (çerez bildirimlerini kaldırma, sabit başlığı serbest bırakma, akordiyonları genişletme) erişim sağlıyoruz.
Web tarayıcıları ve otomatik ekran görüntüsü alma araçları sürekli gelişiyor. Bu nedenle, karşılaştığınız sorunlara yönelik yeni çözümler ve optimizasyonlar bulmak önem taşıyor. Eğer bu konuda deneyimlerinizi veya önerilerinizi paylaşmak isterseniz, lütfen bizimle iletişime geçin. Gelecekteki güncellemelerde daha da gelişmiş çözümler sunmayı hedefliyoruz.
Yapay zeka özeti
Stop Puppeteer fullPage screenshots from hiding or misplacing fixed headers. Learn the root cause and apply a proven fix with JavaScript and CSS tweaks for accurate screenshots.
Etiketler