content-visibility CSS özelliği bu hesabı erteler. Tarayıcıya belirli blokların layout ve paint işlemlerini yalnızca o bloklar görünür alana yaklaştığında çalıştırmasını söyler. Sonuç basit bir resim ertelemesi değil; render motorunun iş yükünü ekran bazında yeniden dağıtmasıdır. İki satır CSS'in bu etkiyi nasıl ürettiğini anlamak için önce tarayıcının ekran dışıyla ne yaptığını görmek gerekir.

Tarayıcı ekran dışını da hesaplar: layout maliyetinin kaynağı

Tarayıcı bir sayfayı işlerken DOM ağacındaki her öğe için boyut, konum ve görünüm hesabı yapar. Layout aşaması adı verilen bu süreç sayfanın tamamını kapsar. Viewport sınırı bu hesabın neyi kapsayacağını belirlemez; sayfa uzunluğu belirler.

Uzun bir ürün listesi sayfasında kullanıcı yalnızca ilk altı kartı görürken arka tarafta 200 kartın daha layout hesabı tamamlanmıştır. Her kartın padding, margin, font boyutu, flexbox veya grid içindeki konumu hesaplanmış; paint aşaması için boyama talimatları üretilmiştir. Bu işlem main thread'de gerçekleşir. İlk yükleme, scroll etkileşimi ve DOM değişiklikleri sırasında bu maliyet yeniden devreye girer.

Render engelleyen kaynaklar genellikle ağ katmanında incelenir; ancak uzun sayfaların render maliyeti doğrudan DOM boyutundan da kaynaklanır. 1500 öğeli bir liste sayfasında ağ katmanı çoktan optimize edilmiş olabilir; bottleneck layout motoruna taşınmıştır. Sorun yalnızca ne yüklendiği değil, yüklenen içeriğin hesaplama motoruna ne kadar iş çıkardığıdır.

`content-visibility: auto` ile hesabı ertelemek

content-visibility: auto direktifi bir öğeye uygulandığında tarayıcı o öğeyi görünürlük yönetimli olarak işaretler. Öğe viewport'tan uzaktaysa layout ve paint hesabı atlanır. Kullanıcı scroll ederek öğeye yaklaştığında tarayıcı bu hesabı o anda çalıştırır.

.article-card {
  content-visibility: auto;
  contain-intrinsic-size: auto 320px;
}

Bu direktifin arka planındaki mekanizma CSS Containment modelidir. content-visibility: auto aynı zamanda o öğeye otomatik olarak contain: layout style paint uygular. Bu değer tarayıcıya şunu söyler: bu bloğun içi dışarıyı, dışarısı içeriği etkilemiyor — ayrı hesaplayabilirsin. Bağımsız hesap, ertelemeye zemin hazırlar.

Kazanım, sayfanın karmaşıklığıyla doğru orantılıdır. Birkaç bölümden oluşan kısa bir blog sayfasında fark ihmal edilebilir düzeyde kalır. Ama yüzlerce karttan oluşan bir e-ticaret listesinde veya yüzlerce yorumun bulunduğu bir tartışma sayfasında ilk render süresi belirgin biçimde kısalır. INP'yi etkileyen uzun görevlerin bir kısmı da aşırı layout hesabından kaynaklanır; content-visibility bu hesabı dağıtarak scroll sırasındaki main thread baskısını azaltır.

`contain-intrinsic-size` olmadan sayfa kayması kaçınılmaz olur

content-visibility: auto uygulanmış bir blok layout'tan çıkarıldığında tarayıcı o bloğun fiziksel boyutunu bilemez. Scrollbar hesabı, toplam sayfa yüksekliği ve diğer öğelerin konumu bu belirsizlikten etkilenir. Kullanıcı scroll çubuğunu sürüklediğinde sayfa içeriği beklenmedik biçimde kayar; bu, doğrudan CLS puanını bozar.

Çözüm contain-intrinsic-size özelliğidir. Bu özellik, öğe henüz layout hesabına girmemişken kullanılacak tahmini boyutu tarayıcıya bildirir. auto anahtar kelimesiyle birleştirildiğinde tarayıcı bir kez hesaplanan gerçek boyutu hatırlar ve sonraki erteleme döngülerinde bu değeri tahmini olarak kullanır:

.article-card {
  content-visibility: auto;
  contain-intrinsic-size: auto 320px;
}

Sabit boyutlu kartlarda — örneğin her biri 280px yüksekliğinde eşit ürün kartları — statik bir değer doğrudan kullanılabilir: contain-intrinsic-size: 280px. Değişken yükseklikteki içerikte auto ile birlikte yaklaşık bir başlangıç değeri vermek, erteleme döngüsü boyunca yeterince kararlı bir davranış sağlar. contain-intrinsic-size atlandığında tarayıcı yüksekliği sıfır kabul eder; sayfa kaydırılırken bloklar aniden yerinden oynayıp scrollbar pozisyonunu bozar. Layout ertelemesinin kazanımı, bu durumda CLS cezasına dönüşür.

Optimizasyona uygun içerik bloğunun profili

content-visibility her senaryoda kazanç sağlamaz. Küçük sayfalar veya az sayıda öğe içeren listeler için ek containment maliyeti bazen kazanımın önüne geçer. Direktifin gerçekten fayda sağladığı durumların belirgin bir profili vardır.

Uzun, tekrarlayan blok yapılarında kazanım en yüksektir: ürün listesi, blog listesi, yorum dizisi, istatistik kartları. Her blok bağımsız olduğu için contain uygulaması doğal oturur. Bloklar arasında boyut veya konum bağımlılığı yoksa tarayıcı her birini gerçekten ayrı hesaplayabilir; erteleme etkisi belirginleşir.

Sabit veya tahmin edilebilir yüksekliği olan içerikler bu optimizasyona daha iyi tepki verir. contain-intrinsic-size tahmininin gerçek boyuta yakın olması, CLS riskini minimize eder. Dinamik içerik — API yanıtına göre değişen kart boyutu, kullanıcıya göre farklı içerik uzunluğu — için auto anahtar kelimesi birinci tercihtir; ancak gerçek boyut hesaplanmadan önce scrollbar hafif titreme üretebilir.

Sticky header, sayfanın tamamını etkileyen animasyon veya position: fixed öğelerin içinde bulunduğu bloklar için dikkatli olunmalıdır. Bu bağlamlarda containment modeli beklenmedik görsel sorunlar üretebilir. Lazy loading ile görüntü erteleme zaten uygulanmış bloklara content-visibility eklemek genellikle gereksizdir; iki mekanizma benzer hedeflere farklı katmanlarda ulaşır ve üst üste bindirilmeleri karmaşıklık yaratır.

Performance panelinde önce/sonra farkını okumak

Chrome DevTools Performance panelinde iki kayıt alınır: biri optimizasyon öncesi, biri sonrası. Her kayıt sayfanın tam yüklenmesinden itibaren ilk scroll hareketini de kapsayacak şekilde tutulur. Karşılaştırma genellikle "Layout" ve "Paint" görevlerinde görünür hale gelir.

Optimizasyon öncesinde main thread'de yükleme anında tek büyük bir layout görevi belirgin biçimde zaman alır. Optimizasyon sonrasında bu görev küçülür; scroll sırasında ise artımlı layout görevleri görünmeye başlar. Bu beklenen davranıştır — layout ortadan kalkmamış, dağılmıştır. Ana thread üzerindeki yük yayıldığı için uzun görev sayısı azalır ve kullanıcı etkileşimlerine verilen yanıt hızlanır.

"Rendering" sekmesindeki "Layout Shift Regions" seçeneği contain-intrinsic-size yapılandırmasını doğrulamak için kullanılır. Tahmin değeri gerçek boyuttan çok uzaksa, scroll sırasında mavi çerçeveler sürekli belirmaya devam eder. Doğru yapılandırılmış bir değerle bu çerçeveler yalnızca bloğun ilk görünür olduğu anda kısaca belirir, ardından kaybolur. Core Web Vitals ölçümünde CLS üzerindeki etkiyi saha verisinde görmek birkaç gün alabilir; lab verisi değişimi hemen yansıtır.

LCP açısından da dolaylı bir kazanım söz konusudur. Main thread'in yük anındaki baskısı azaldığında en büyük içerik öğesinin render'ı öne çekilebilir. Bu etki doğrudan bir LCP optimizasyonu değil; layout maliyetinin azalmasının yan ürünüdür. Bununla birlikte, main thread'in boşalması zaman açısından hassas olan LCP öğesinin zamanında işlenmesine katkıda bulunur.

content-visibility: auto sürpriz derecede küçük bir CSS değişikliğidir; ama layout motorunun çalışma biçimini köklü biçimde etkiler. Uzun sayfaların render maliyetinin büyük bölümü gereksiz yere ekran dışına harcanır ve bu özellik o harcamayı erteler. İki satır CSS ile başlayıp DevTools'ta önce/sonra kayıt karşılaştırması yapılabilir; kazanım görünür olduğunda optimizasyonu diğer bloklara genişletmek kolaylaşır.

Kullanıma hazır hale getirmek için contain-intrinsic-size zorunludur — atlandığında CLS cezası kazanımın önüne geçer. Hedef öğelerin profilinin doğru okunması da en az direktifin kendisi kadar önemlidir: doğru blok yapısında uygulandığında bu özellik, ağ katmanına hiç dokunmadan render performansına somut bir katkı sunar.